leetcode 10 正則表達式匹配


描述:

實現.和*號匹配,*表示前面字符0~無窮個,.表示任意一個字符。

要求全部,匹配,不是部分匹配。

 

解決:

思路類似最長公共子序列,

dp[i][j] = dp[i - 1][j - 1], 如果s[i] == p[j] || p[j] == '.'

              dp[i][j - 2], 如果p[j] == '*' && s[i] != p[j - 1]

              dp[i - 1][j] || dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 1][j - 2] || dp[i][j - 2], 如果p[j] == '*' && s[i] == p[j - 1]

稍稍解釋下:

對於s和p,設各個最后一個字符為x, y,p的倒數第二字符為z,除此外前面字符設為S,P,則:

s = Sx

p = Pzy

如果x == y或y == '.',則如果S和Pz匹配,則s和p匹配,因為最后兩字字母是匹配的。這就縮減了問題規模。

而對於y ==  '*'的情況,需要考慮z:

    如果x != z,則只有在s和P匹配的情況下,s和p才匹配。

    如果x == z,設匹配符號為~吧,方便,則如果S~P,S~Pz,S~Pzy,Sx~P,Sx~Pz,都可得出s和p匹配。

 

代碼壓縮了空間,用一些額外變量保存會用到的變量。時間復雜度O(m*n),空間復雜度O(n)。

bool cmatch(char s, char p) {
    return p == '*' || p == '.' || s == p;
}

bool isMatch(string s, string p) {
    int m = s.size();
    int n = p.size();
    bool* arr = new bool[n + 1]();
    arr[0] = 1;

    for (int i = 2; i <= n; ++i)
        if (p[i - 1] == '*' && arr[i - 2] == true) arr[i] = true;

    int j2 = arr[0];
    int j1 = arr[1];
    int sa = arr[2];

    for (int i = 1; i <= m; ++i) {
        for (int j = 0; j <= n; ++j)
            if (j == 0) {
                j2 = arr[0];
                arr[0] = false;
            }
            else if (j == 1) {
                j1 = arr[1];
                arr[1] = i == 1 && cmatch(s[0], p[0]);
            }
            else {
                sa = arr[j];
                if (p[j - 1] == '*')
                    arr[j] = cmatch(s[i - 1], p[j - 2]) && (arr[j] || arr[j - 1] || j1 || j2 || arr[j - 2])?true:arr[j - 2];
                else
                    arr[j] = cmatch(s[i - 1], p[j - 1])?j1:false;
                j2 = j1;
                j1 = sa;
            }
    }
    return arr[n];
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM