1. 程式人生 > 實用技巧 >LeetCode——正則表示式匹配

LeetCode——正則表示式匹配

題目地址:https://leetcode-cn.com/problems/regular-expression-matching/

解題思路:首先很明顯字串的匹配適合動態規劃,所以建立dp[i][j]表示s的前i個字元與p中的前j個字元是否能夠匹配。然後就是判斷各種情況。筆者在寫的時候情況考慮不全導致沒有通過。

"aab"
"c*a*b"

"aa"
"a*"

""
"."

所有情況的歸納:

如果 p.charAt(j) == s.charAt(i) : dp[i][j] = dp[i-1][j-1];
如果 p.charAt(j) == '.' : dp[i][j] = dp[i-1][j-1];

如果 p.charAt(j) == '*':
  如果 p.charAt(j-1) != s.charAt(i) : dp[i][j] = dp[i][j-2] //in this case, a* only counts as empty
  如果 p.charAt(i-1) == s.charAt(i) or p.charAt(i-1) == '.':
    dp[i][j] = dp[i-1][j] //in this case, a* counts as multiple a
    or dp[i][j] = dp[i][j-1] // in this case, a* counts as single a
    or dp[i][j] = dp[i][j-2] // in this case, a* counts as empty

class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size();
        int n = p.size();
        int i, j;
        //dp[i][j]:表示s的前i個字元與p中的前j個字元是否能夠匹配。
        vector<vector<bool>> dp(m + 1, vector<bool
>(n + 1)); dp[0][0] = true; //設定邊界,避免越界 for (i = 1; i <= m; i++) dp[i][0] = false; for (j = 1; j <= n; j++) if (p[j - 1] == '*') dp[0][j] = dp[0][j - 1] || dp[0][j - 2]; else dp[0][j] = false; //正常判斷 for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) { if (j == 1) if (i == 1) dp[1][1] = s[0] == p[0] || p[0] == '.'; else dp[i][j] = false; else { if (p[j-1] == '*') { if (p[j - 2] != s[i-1] && p[j - 2] != '.') dp[i][j] = dp[i][j - 2];//如果最後一個字元不相等,則把*前的一個字元刪去:aa與aab*;aabc與aab* else if (p[j - 2] == s[i-1] || p[j - 2] == '.') dp[i][j] = dp[i - 1][j] || dp[i][j - 1] || dp[i][j - 2];//分別是匹配多個,匹配一個,匹配0個 } else if (p[j-1] == '.') dp[i][j] = dp[i - 1][j - 1];//如果是'.',直接判斷兩個字串前i-1,j-1是否匹配。 else dp[i][j] = s[i-1] == p[j-1] && dp[i - 1][j - 1]; } } return dp[m][n]; } };