先上代码:
class Solution {
public:
bool isMatch(string s, string p) {
if (p.empty()) //如果p为空的话返回值也为空
if ('*' == p[1])//如果下一个字符('*'不能出现在字符串的开头)为'*'
// x* matches empty string or at least one character: x* -> xx*
// *s is to ensure s is non-empty
return (isMatch(s, p.substr(2)) || !s.empty() && (s[0] == p[0] || '.' == p[0]) && isMatch(s.substr(1), p));
else
return !s.empty() && (s[0] == p[0] || '.' == p[0]) && isMatch(s.substr(1), p.substr(1));
}
};
其中最后的两个return语句是这段代码的核心,可能多个逻辑符放一起看起来有点杂,现在我们现在来分析一下:
先看其中的第一个,可将其拆分为如下两行(更直观一些)
(isMatch(s, p.substr(2)) ||
!s.empty() && (s[0] == p[0] || '.' == p[0]) && isMatch(s.substr(1), p))
对该语句中每个逻辑表达式进行分析:
①首先,第一个substr函数中的'2'代表对'*'对应字符后的字符串进行判断(注意将或运算符中的右边全部看为一个整体????),如果该语句为
真的话可直接判断为相匹配(返回值为true,注意'*'操作符可匹配前边的字符0次,相当于起到删除的作用)
否则的话,因为p字符串里边两个抽象的符号在符合条件下是可以与任意字符相匹配,所以还要进行进一步的判断。
②如果具体的字符串s不为空为真(空的话代表什么都没有,自然无法匹配喽)。而且因为p字符串里边既可以出现抽象的匹配符也可以出现具体的
字符,所以有两种情况都符合匹配的条件。(要注意字符串p的开头只能是具体字符或'.')
③此处运用了递归的思想,注意substr函数在这样的格式下返回的是原字符串从第i个字符串起之后的全部,故相当于逐渐将字符串"缩短",并
逐一进行判断。
④在理解了当p字符串中第二个元素为'*'的基础上之后,那么理解当其不为'*'的情况也就容易多了。
同样地,字符串s满足不能为空的条件,括号里的第二个逻辑表达式的意义上述已经提到,还要满足从第二个元素(注意和数组相同,第一个元素下标为1
)开始时的递归.
在理解了第一个语句的基础上不难据此推断出第二个return语句的作用。