LeetCode 10. 正規表示式匹配

董洞洞同學發表於2020-10-07

題目描述

這裡寫圖片描述

解題思路

1. 暴力遞迴

這道題與劍指offer中的“正規表示式”,有相似之處。
區別在於,劍指offer中那道題好像是不處理”a”, “a*…a*”這種情況,即為主串為空,但是模式串不為空的情況,因此,加上對這種情況的特判即可。
主要是要保證,當模式串不為空時,後面的號表示前面的字元一個都不取,舉例:”a” 可以與“aa*b*c*d,只要這種間隔出現的時候才可以,特判一下即可。

程式碼實現

class Solution
{
public:

    bool Judge(char* str1, char* str2)
    {
        //cout<<*str1<<" "<<*str2<<endl;
        if(*str1 == '\0' && *str2 == '\0')
            return true;
        if(*str1 != '\0' && *str2 == '\0')
            return false;

        if(*str1 == '\0' && str2 != '\0')
        {
            int flag = false;
            while(*str2 != '\0')
            {
               if(*str2 != '*' && *(str2+1) != '*')
               return false;

               if(*str2 == '*')
                flag = true;
               else
                flag = false;
               str2++;
            }
            return flag;

        }

        if(*(str2+1) == '*')
        {
            if(*str1 == *str2 || (*str2 == '.'))
                return Judge(str1, str2+2) || Judge(str1+1, str2+2) || Judge(str1+1, str2);
            else
                return Judge(str1, str2+2);
        }

        if(*str1 == *str2 || (*str2 == '.'))
            return Judge(str1+1, str2+1);
        return false;
    }

    bool isMatch(string s, string p)
    {
        char str1[550];
        char str2[550];
        int len1 = s.length();
        int len2 = p.length();
        if(len1 == 0 && len2 == 0)
            return true;
        for(int i = 0; i < len1; i++)
            str1[i] = s[i];
        str1[len1] = '\0';

        for(int i = 0; i < len2; i++)
            str2[i] = p[i];
        str2[len2] = '\0';
        return Judge(str1, str2);
    }
};

2. 動態規劃

第一種解法雖然可以過,但是效率是非常低的,因此可以用動態規劃來解決,思路基於第一種的思路。
動態規劃解法如下:
定義一個二維的DP陣列,其中dp[i][j]表示s[0,i)和p[0,j)是否match,然後有下面三種情況
1. dp[i][j] = dp[i - 1][j - 1], if p[j - 1] != ‘*’ && (s[i - 1] == p[j - 1] || p[j - 1] == ‘.’);
2. dp[i][j] = dp[i][j - 2], if p[j - 1] == ‘*’ and dp[i][j-2] (代表模式串*前的元素未匹配;)
3. dp[i][j] = dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == ‘.’), if p[j - 1] == ‘*’ and dp[i-1][j] (代表主串中上一個元素已經被*前面的元素取代過)

程式碼如下

class Solution
{
public:

    bool isMatch(string s, string p)
    {
        int n = s.size();
        int m = p.size();
        bool dp[1010][1010];
        memset(dp, false, sizeof(dp));
        dp[0][0] = true;
        for(int i = 0; i <= n; ++i)
        {
            for(int j = 1; j <= m; ++j)
            {
                if(j > 1 && p[j-1] == '*')
                    dp[i][j] = dp[i][j-2] || (i > 0 && (s[i-1] == p[j-2] || p[j-2] == '.') && dp[i-1][j]);
                else
                    dp[i][j] = i > 0 && dp[i-1][j-1] && (s[i-1] == p[j-1] || p[j-1] == '.');
            }
        }
        return dp[n][m];
    }
};

相關文章