1. 程式人生 > >Regular Expression Matching【難】

Regular Expression Matching【難】

Regular Expression Matching

Leetcode真的是一個不錯的網站,全世界的人都在上面刷題,上面的題還是挺好的。現將我在上面做過的題寫成解題報告,既是一種分享也是一個記錄防止日後自己在轉過頭來看自己的解法又看不懂了。好了廢話不多說

Regular Expression Matching題目大致意思是實現一個正則表示式支援’.’’*’兩種特殊符號,其匹配規則如下:

(1)’.’可以匹配任意單個字元

(2)‘*’可以匹配0個或多個前導符號,即該符號之前的一個字元

需要注意的是匹配過程需要完全匹配,而不是部分也就是說s,p兩個字串,匹配完之後s,p不能有再多餘的字元

難度:難

例子:

isMatch("aa","a") → false

isMatch("aa","aa") → true

isMatch("aaa","aa") → false

isMatch("aa", "a*") → true

isMatch("aa", ".*") → true

isMatch("ab", ".*") → true

isMatch("aab", "c*a*b") → true

isMathc(“abc”, “a*b*c*) → true

倒數第二個例子可以理解為*可以消除前導符號,最後一個例子則說明*可以匹配0個字元

思路:

剛開始做的時候認為這道題沒有甚麼特殊的,直接一個一個字元進行匹配。當WA

了幾次之後仔細思考才發現到了匹配過程中達到某一個狀態可能有多種策略,這個時候立馬想到可以通過回朔或者動態規劃來解。於是當然選擇了動態規劃,因為可以避免重複計算

對於任意一個狀態m[i][j]表示用j個字元匹配待匹配串i個字元是否能夠匹配成功;經分析可以有5種策略轉移到該狀態上:

(1)當p[j]=’*’時只要當j-1個字元能夠成功匹配i個字元即可,此時p[j]匹配0個字元即m[i][j] = m[i][j-1] (j>=1)

(2)當p[j]=’*’時,可以j-2個字元能夠成功匹配i個字元即可,此時消除p[j]可以消除p[j-1]m[i][j] = m[i][j-2] (j >= 2)

(3)當p[j]=’*’,此時p[j]可以向後擴充套件前導符號p[j-1]即可以在j個字元匹配好i-1個字元後通過擴充套件一個字元繼續和第i個字元匹配則m[i][j] = m[i-1][j] && (p[j-1] == s[i] || p[j-1] == ‘.’) (i>= 1 && j >= 1)

(4)當p[j]=’*’,此時p[j]除了可以像第三種方式擴充套件之外還可以在第j-1個字元成功匹配第i-1個字元後再繼續匹配第i個字元。則m[i][j] = m[i-1][j-1] && (p[j-1] == s[i] || p[j-1] == ‘.’) (i >= 1 && j >= 1)

(5)當p[j]為普通字元或者是’.’符號時,m[i][j] = m[i-1][j-1] && (p[j] == s[i] || p[j] == ‘.’) (i >= 1 && j >= 1)

邊界情況討論,從上述5中測錄俄可以看出j或者i都必須大於等於1,而字元下標是從0開始的,為了能夠匹配到所有的所有的字元這裡m[1][1]表示第0個字元匹配第0個字元,而且沒有狀態能夠轉移到m[0][0]狀態,所以需要手動賦值。m[0][0]需要賦成甚麼值需要具體討論由這個狀態轉移到後續的某個狀態的結果從而確定這個值是true還是false。程式碼如下:

class Solution {

public:

    bool isMatch(string s, string p) {
        int iLens = s.length();
        int iLenp = p.length();
        
        int i, j, k;
        bool m[1000][1000] = {false};
        m[0][0] = true;
        
        bool bRet = false;

        for(i = 0; i <= iLens; i ++)
        {

            for(j = 1; j <= iLenp; j ++)
            {

                if(j >= 1 && p[j - 1] == '*')
                {
                    bRet = m[i][j - 1];
                    m[i][j] = m[i][j] > bRet ? m[i][j] : bRet;
                }

                if(j >= 2 && p[j - 1] == '*')
                {
                    bRet = m[i][j - 2];
                    m[i][j] = m[i][j] > bRet ? m[i][j] : bRet;
                }
                if(i >= 1 && j >= 2 && p[j - 1] == '*')
                {
                    bRet = m[i - 1][j - 1] && ( (s[i - 1] == p[j - 2]) || (p[j - 2] == '.') );
                    m[i][j] = m[i][j] > bRet ? m[i][j] : bRet;
                }
                if(i >= 2 && j >= 1 && p[j - 1] == '*')
                {
                    bRet = m[i - 1][j] && ( (s[i - 1] == p[j - 2]) || (p[j - 2] == '.') );//p字元比s字串短,*結尾
                    m[i][j] = m[i][j] > bRet ? m[i][j] : bRet;

                }
                if(i >= 1 && j >= 1)
                {
                    bRet = m[i - 1][j - 1] && ( (s[i - 1] == p[j - 1]) || (p[j - 1] == '.') );
                    m[i][j] = m[i][j] > bRet ? m[i][j] : bRet;
                }
            }
        }
        //std::cout<<iLens<<" "<<iLenp<<std::endl;
        //for(i = 0; i <= iLens; i ++)
        //{
        //    for(j = 0; j <= iLenp; j ++)
        //        std::cout<<m[i][j]<<" ";
        //    std::cout<<std::endl;
       // }

       return m[iLens][iLenp];
    }

};