Leetcode 10 Regular Expression Matching (dp)

给出两个字符串s、p,'.'可以匹配任意一个字符,'*'可以将其前一个的字符重复任意次数,也可以重复0次(ab*可以表示ab、abb,也可以表示a),问是否可以匹配成功。

应该算是比较明显的动态规划吧,一看就猜是动态规划,不过leetcode是没有数据范围的,不知道比较暴力的方法能不能过。虽然很快看出来了,但是太久没写过dp了,调了好久才好。

好,说重点,我用dp[i][j]表示s的前i个和p的前j个是否能成功匹配(其实*会打破这个定义,但是不会影响结果的正确性)。如果p[j]是'.'或者普通字符且与s[i]相等的话很简单 ,就是dp[i  + 1][j + 1] |= dp[i][j],p[j]是*的话就会比较复杂,四种情况:

  1. *和前一个字符不匹配,则i不变,j后移两个(从j-1到j+1,即放弃p[j-1])  \large dp[i][j + 1] |= dp[i][j - 1]

  2. 跳过*,j后移一位,\large dp[i][j + 1] |= dp[i][j]

  3. *重复前一个字符串且仅重复这一次,i和j均后移一位,并且要判断p[j - 1]和s[i]是否匹配\large dp[i + 1][j + 1] |= dp[i][j] && (p[j - 1] == '.' || p[j - 1] == s[i])

  4. *重复前一个字符并保留*继续向前匹配,即i后移一位j不懂,同样要判断p[j - 1]和s[i]是否匹配\large dp[i + 1][j] |= dp[i][j] && (p[j - 1] == '.' || p[j - 1] == s[i]);(这一种情况破坏了dp[i][j]的定义)。

代码如下:

class Solution {
public:
    bool isMatch(string s, string p) {
        vector > dp(s.size() + 2, vector(p.size() + 2, 0));
        dp[0][0] = 1;
        for(int j = 0; j <= p.size(); j++) {
            for(int i = 0; i <= s.size(); i++) {
                //if(dp[i][j] == 0) continue;
                if(p[j] == '.' || p[j] == s[i]) dp[i + 1][j + 1] |= dp[i][j];
                if(p[j] == '*' && j) {
                    dp[i][j + 1] |= dp[i][j];
                    dp[i][j + 1] |= dp[i][j - 1];
                    dp[i + 1][j + 1] |= dp[i][j] && (p[j - 1] == '.' || p[j - 1] == s[i]);
                    dp[i + 1][j] |= dp[i][j] && (p[j - 1] == '.' || p[j - 1] == s[i]);
                }
            }
        }
        return dp[s.size()][p.size()];
    }
};

 

你可能感兴趣的:(dp)