【leetcode】10. 正則表達式匹配(regular-expression-matching)(DP)[困難]

鏈接

https://leetcode-cn.com/problems/regular-expression-matching/

題意

給你一個 匹配串 s 和一個 模式串 p,實現一個支持 ‘.’‘*’ 的正則表達式匹配。

’.’ 匹配任意單個字符
’*’ 匹配零個或多個前面的那一個元素

思路

動態規劃。

dp[i][j]dp[i][j] 表示 s[i:]s[i:]p[j:]p[j:] 是否能匹配。自底向上計算。

因爲有 ‘*’’*’ 比較麻煩,它會出現在當前匹配的字符的後面,匹配零個或任意多個當前元素。也就是說可以有 任意多個 當前字符,也可以 沒有(忽略)。[0,)[0, \infty)

分兩種情況討論:
first_match=(s[i]==p[j]p[j]==.)first\_match = (s[i] == p[j] 或者 p[j] == '.') (當前字符是否匹配)

  1. 當前字符後面是 ‘*’ 的情況,if(j+1 < p.size() && p[j+1] == '*'),可以有兩種選擇,忽略 模式串p 的這個字符(0個),或者在匹配當前字符的情況下 模式串p不動 繼續匹配剩下的 匹配串s(任意多個)。
    dp[i][j]={dp[i][j+2]  (0)dp[i][j]=first_match && dp[i+1][j]  ()dp[i][j] = \begin{cases} dp[i][j+2] \ \ (0個) \\ dp[i][j] = first\_match \ \&\&\ dp[i+1][j] \ \ (任意多個) \end{cases}
  2. 沒有 ‘*’ 的情況,直接匹配當前字符和剩下的串即可:
    dp[i][j]=first_match && dp[i+1][j+1]dp[i][j] = first\_match \ \&\&\ dp[i+1][j+1]

PS: 初始化時需要注意

  1. j == p.size()相當於 模式串 p 爲空,只要 匹配串 s 不爲空,一定匹配失敗。 dp[i][p.size()]=0dp[i][p.size()] = 0
  2. i== s.size()相當於 匹配串 s 爲空,這時 模式串p 可以不爲空而匹配成功,eg:s = "", p = "a*"
  3. 模式串p匹配串s 都爲 空 是匹配成功的。dp[s.size()][p.size()]=1dp[s.size()][p.size()] = 1

AC代碼

class Solution {
public:
    bool isMatch(string s, string p) {
        bool dp[s.size()+1][p.size()+1];
        for(int i = 0; i < s.size(); ++i) dp[i][p.size()] = 0; // j == p.size()相當於 模式串 p 爲空,只要 匹配串 s 不爲空,一定匹配失敗。
        dp[s.size()][p.size()] = 1; // 模式串 和 匹配串 都爲 空 可以匹配成功
        for(int i = s.size(); i >= 0; --i) { // i 從 s.size() 開始是因爲 匹配串s 爲空,模式串p 可以不爲空而匹配成功,eg:s = "", p = "a*";
            for(int j = p.size()-1; j >= 0; --j) {
                bool first_match = i < s.size() && (s[i] == p[j] || p[j] == '.');
                if(j+1 < p.size() && p[j+1] == '*') {
                    dp[i][j] = dp[i][j+2] || (first_match && dp[i+1][j]);
                }
                else {
                    dp[i][j] = first_match && dp[i+1][j+1];
                }
            }
        }        
        return dp[0][0];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章