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<vector<int> > dp(s.size() + 2, vector<int>(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()];
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值