一道leetcode的 递推关系的问题(动态规划)

描述:一般字符串s 和 “模式串p” 是否 能够匹配的问题

请实现一个函数用来匹配包含'. ''*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a""ab*ac*a"匹配,但与"aa.a""ab*a"均不匹配。

解:

1.关键:

(1)好吧,我承认, 思路是借鉴评论区 的

(2)转移 状态 就是 前 s的前i个字符串 和 p的前j个字符串是否匹配

(3)设置一个 dp 矩阵 dp[s.size+1][p.size+1]  //这么干 是为了 多出一种 “空 字符串的 情况

(4)分2中情况考虑 递推关系:

case1: 如果p[j-1]==‘*’(备注:从下标0开始用):

<1>可以 利用dp[i][j-2] 并且 让* 和它前面的那个字符 ”消失“

<2>可以利用dp[i-1][j] 并且 p[j-1]=='.' 万能的. , 不过这里 最难理解: 就是说 ,算了,这里有点不理解

Why?? 为什么 是dp[i-1][j] == true的时候呢???

答:可以 参见 题解中大佬题解的 评论区 "哦妈呀"的那位的 评论 解释, 很不错

解释一下当p[j - 1] == * 时,可以看到23这两种情况中,模式串下标索引为 j,而不是 j-1

因为根据定义,* 前一字符可以出现任意次。重点注意任意次(情况23其实是,前一次字符出现次数为1次及以上)。

以 "aaa" 和 "a*" 这个例子为例,根据递推公式,当p[j - 1] == * ,dp[i][j] 状态值取决于 dp[i-1][j] == true && s[i - 1] == p[j - 2]。 我们思考的过程如下:

  1. "a*" 是否能和 "aaa"匹配 这取决于:

  2. "a*" 能否和 "aa" 匹配,而这种情况又取决于:

  3. "a*" 能否和 "a" 匹配,毫不例外的,这种情况又依赖于于:

  4. "a*"能否和 ""(空串) 匹配,这时满足情况1,即 p[j-2]*的组合将前一字符出现次数看作 0。 "a*"和 ""(空串) 匹配嘛。 答案当然是匹配的!!!

反过来想,如果下标我就是要写成 j - 1呢???
这就意味着状态转移变为: dp[i][j] 状态值取决于 dp[i-1][j-1] == true && s[i - 1] == p[j - 2],这其实变相就是默认 * 只能让前一字符 p[j - 2] 出现一次,仅仅是一次!。仔细观察 ’.‘ 通配符,它能让当前字符变为任意1个(划重点,也是1)字符,关于它的递推公式中,模式串下标好巧不巧,也是 j-1。这样一对比就很明显了。

回到刚才的例子 所以 "a*" 是否能和 "aaa" 匹配 ,这取决于 "a" 能否和 "aa" 匹配嘛? 这当然不取决于 "a" 能否和 "aa" 匹配,因为这种递推关系本质上就错了,结果也一定是错的。

<3>可以

case2:如果 p[j-1]!=* 

<1>可以利用 dp[i-1][j-1] 并且 s[i-1] == p[j-1] 这个容易理解, 就是 最新加入的 两个字符 相等

<2>可以利用 dp[i-1][j-1] 并且 p[j-1] == '.' 只要 这个 位置 p模式串的字符 是万能字符 即可

2.代码:

class Solution {
public:
    bool isMatch(string s, string p) {
        //关于 字符串的 模式匹配的 问题 考虑借鉴 讨论区的 想法
        //利用 dp 动态规划 矩阵 进行 求解
        // size1+1 = m , size2+ 1 =n
        int m=s.size()+1;
        int n = p.size() + 1;

        vector> dp(m,vector(n,false)); // 初始化一个矩阵
        //如果 s是一个空的 字符串 , 需要 让字符串p进行 匹配 , 只有* 
        //这个道具 让字符串p 变成一个空的字符串 ,
        //然后 将 p 和 一个空字符串 进行 匹配的 结果 作为 递推 关系的 初始条件
        dp[0][0]=true; // 2个空的 字符串 一定是匹配的 
        //如果 字符串p有 奇数个 字符 一定不可能匹配
        for(int j=2; j 

你可能感兴趣的:(leetcode,动态规划,算法)