描述:一般字符串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] == *
时,可以看到2
、3
这两种情况中,模式串下标索引为j
,而不是j-1
因为根据定义,
*
前一字符可以出现任意次。重点注意任意次(情况2
、3
其实是,前一次字符出现次数为1次及以上
)。以
"aaa"
和"a*"
这个例子为例,根据递推公式,当p[j - 1] == *
,dp[i][j]
状态值取决于dp[i-1][j] == true
&&s[i - 1] == p[j - 2]
。 我们思考的过程如下:
"a*"
是否能和"aaa"
匹配 这取决于:
"a*"
能否和"aa"
匹配,而这种情况又取决于:
"a*"
能否和"a"
匹配,毫不例外的,这种情况又依赖于于:
"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 =nint 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