劍指offer——正規表示式匹配C++

baixiaofei567發表於2021-01-05

在這裡插入圖片描述
難點有2
1:理清思路很難。2:"“的匹配有很多情況不知道到底是匹配幾個很難。
這裡我們用的是遞迴求解。分情況:先看pat的下一個是否為” * “,如果是,那麼又有兩種情況,當前位是否匹配,如果當前位匹配(可以用兩個字串當前字元相等或者pat當前字元為”.“來判斷),那麼要看接下來這個”
“到底要匹配多少次了。第一種情況aa和aaa,匹配0次;第二種情況aa和aa,匹配1次;第三種情況aaab和a*b匹配多次。所以我們遞迴判斷每一種情況,只要有一種為true,那麼就是true,用||運算子。匹配0次是str不動,pat後移兩位…以此類推即可。
如果不能匹配,那麼 一定是匹配0次的,所以遞迴判斷str不變,pat後移兩位。
如果下一位不為"
”,如果匹配(也是用兩個式子判斷)就均移一位。如果不匹配,就是false。
細節需要很注意,遞迴邊界以及一開始的邊界條件char * 是否為空用==’\0’來判斷,遞迴邊界是如果兩者同時走到底就是true,走到是當前位等於長度,而不是長度-1。如果pat走到底了,str沒到底,就是false。
還有一個細節是每次都要判斷是否會越界!這很重要,要放在&&的前面,後面才是取字元

class Solution {
public:
    bool helpMatch(string str,int strIndex,string pattern, int patIndex){
        //遞迴函式,遞迴邊界和遞迴式
        //這裡的遞迴式分情況討論
        //遞迴邊界就是一邊到底了,一邊沒到;或者兩邊都到了就是true
        if(str.length() == strIndex && pattern.length() == patIndex){
            return true;
        }
        //如果pat到底了,str沒到底,就是false,因為pat一般來說走的比較快
        if(pattern.length() == patIndex && str.length() != strIndex){
            return false;
        }
        //分情況,主要是看下一個是否為'*',先確保長度不會超,用&&
        if(patIndex < pattern.length()-1 && pattern[patIndex+1] == '*'){
            //又要分情況,如果當前位是匹配的,分3種情況
            if(str[strIndex] == pattern[patIndex] || (strIndex != str.length() && pattern[patIndex] == '.')){
                //第一種aa和a*aa,匹配0次,所以pat往後移兩位
                //第二種ab和a*b,匹配1次,所以str往後1位,pat往後2位
                //第三種aab和a*b,匹配多次,但是你不知道具體要匹配幾次,
                //就一步一步往後推,str一位一位往後即可。遞迴要做的就是目前要做的事,後面的事交給後面的遞迴
                //pat不變
                return (helpMatch(str,strIndex,pattern,patIndex+2) ||
                       helpMatch(str,strIndex+1,pattern,patIndex+2)||
                       helpMatch(str,strIndex+1,pattern,patIndex));
            }
            else{
                //如果是不匹配的,那麼只能匹配0次,str不動,pat後2位
                return helpMatch(str,strIndex,pattern,patIndex+2);
            }
        }
        //下一位不是*,正常匹配,如果不匹配,直接false
        if(patIndex < pattern.length() && pattern[patIndex+1] != '*'){
            if(str[strIndex] == pattern[patIndex] || (pattern[patIndex]=='.' && strIndex != str.length())){
                return helpMatch(str,strIndex+1,pattern,patIndex+1);
            }
        }
        return false;
    }
    
    bool match(char* str, char* pattern)
    {
        //主要是要分清楚所有情況
        //str是字串,pattern是模式串
        //先考慮只有".",沒有"*"的情況,如果當前字元相等或者pattern[j]=='.'都算匹配上了
        //繼續考慮"*",如果在匹配的情況下
        /*int i = 0, j = 0;
        //先強轉
        string a = str, b = pattern;
        while(i < a.length()&& j < b.length()){
            if(a[i] == b[j] || b[j] == '.'){
                //匹配成功
                if(j < b.length()-1 && b[j+1] == '*'){
                    //匹配0次或者匹配多次
                }
                else{
                    i++;
                    j++;
                }
            }
            else{
                if(j < b.length() - 1 && b[j+1] == '*'){
                    //只能匹配0次
                }
                else{
                    return false;
                }
            }
        }
        return i == j;*/
        if(*str == '\0' && *pattern == '\0') return true;
        if(*pattern == '\0') return false;
        string a = str, b = pattern;
        int strIndex = 0, patIndex = 0;
        return helpMatch(a,strIndex,b,patIndex);
    }
};

相關文章