这道题直接看的答案。但即使看答案也废了不少劲
先看递归的完整代码
class Solution {
public:
bool isMatch(string s, string p) {
if (p.empty())
return s.empty();
bool first=!s.empty()&&(p[0]=='.'||s[0]==p[0]);
if (p[1]=='*')
return first&&isMatch(s.substr(1),p)||isMatch(s,p.substr(2));
else
return first&&isMatch(s.substr(1),p.substr(1));
}
};
第一个点
if (p.empty())
return s.empty();
开始的某个边界条件,p和s不能交换位置,因为如果是"“和”*a"的话,s为空,但是p不为空。但是实际返回结果是true。
第二个点
那s先为空的情况如何呢?s先为空的话,说明字符串对比失败了呀。所以可以在first里添加,将这个条件作为第一位。
bool first=!s.empty()&&(p[0]=='.'||s[0]==p[0]);
第三个点
这里三个bool值的顺序不能错
if (p[1]=='*')
return first&&isMatch(s.substr(1),p)||isMatch(s,p.substr(2));
不能写成像下面这样,这二者不等价。
if (p[1]=='*')
return isMatch(s,p.substr(2))||first&&isMatch(s.substr(1),p);
同样这里包含了第四个点
因为先是first的&&,所以当s为空时,s.substr(1)会被跳过,不会执行,也不会因此发生越界的情况。
first&&isMatch(s.substr(1),p)||isMatch(s,p.substr(2))
第五个点
也不用担心下面p这里会越界,首先进行到这一步,p必然非空,如果非空,那么p至少有一个元素,,所以即使p只有一个字符,那p[1]也是存在的,因为字符串实际是n+1个字符,最后一个字符是’\0’结尾的。
if (p[1]=='*')
动态规划其实也是暴力解法,只是看作是有记忆功能的递归,省去了重复的步骤。而先写出递归,对写出状态转移方程也是有好处的。下面的图少写了p[j]=’.’。
试了几次,写不出DP的代码,折磨了一天,发现里面坑太多,放在另一篇里单独说了。
https://blog.csdn.net/meixingshi/article/details/112799026