leetcode10.正则匹配(依旧是学习大佬的)

这题我懵逼很久,题目描述也不太明白,“就是说,字符串a*b,可以表示b或是aaab,即a的个数任意,(https://www.cnblogs.com/grandyang/p/4461713.html)”,看到大佬的讲解我才明白,主要是学习dp的,然后就去找子结构,这个不用说是s,p的最大的匹配数作为dp的两个索引,决策量我找的是匹配的长度,然后就是方程了,我只想到了两种情况,下面记录一下大佬的(https://www.cnblogs.com/willaty/p/8134672.html):

思路类似最长公共子序列,

dp[i][j] = dp[i - 1][j - 1], 如果s[i] == p[j] || p[j] == '.'

              dp[i][j - 2], 如果p[j] == '*' && s[i] != p[j - 1]

              dp[i - 1][j] || dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 1][j - 2] || dp[i][j - 2], 如果p[j] == '*' && s[i] == p[j - 1]

稍稍解释下:

对于s和p,设各个最后一个字符为x, y,p的倒数第二字符为z,除此外前面字符设为S,P,则:

s = Sx

p = Pzy

如果x == y或y == '.',则如果S和Pz匹配,则s和p匹配,因为最后两字字母是匹配的。这就缩减了问题规模。(dp[i][j] = dp[i - 1][j - 1], 如果s[i] == p[j] || p[j] == '.')

而对于y ==  '*'的情况,需要考虑z:

    如果x != z,则只有在s和P匹配的情况下,s和p才匹配。就是可以简单的想一下p=Sxz*,*可以吃掉z然后和两个就匹配上了,由于字符串递归 的性质这个可以是中间的一个过程( dp[i][j] =dp[i][j - 2], 如果p[j] == '*' && s[i] != p[j - 1])

    如果x == z,设匹配符号为~吧,方便,则如果S~P(p=Sx*,dp[i - 1][j - 2] ),S~Pz(p=S*,*取x,变p=Sx,dp[i - 1][j - 1] ),S~Pzy(最后的*可以再变出来一个x,dp[i - 1][j]),Sx~P(*吃掉p最后的x,dp[i][j - 2],),Sx~Pz(*自杀,dp[i][j - 1]),Sx~Pzy没必要想了,就是前一种情况,都可得出s和p匹配。这几种情况不容易想全了,要是没有顺序的话,大佬这么列就是2*3的组合了,但是看了另一个大佬的这个还可以再简化,世界真奇妙,有木有

int m = s.size(), n = p.size();
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
        dp[0][0] = true;
        for (int i = 0; i <= m; i++) {//i,j是第i,j个字符不是字符串中的索引
            for (int j = 1; j <= n; j++) {
                if (p[j - 1] == '*') {//反正无论如何都可以是dp[i][j-2],
                    dp[i][j] = dp[i][j - 2] || (i && dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.'));
                } else {//对应第一种情况
                    dp[i][j] = i && dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
                }
            }
        }
        return dp[m][n];
    }

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值