基本思想,逐个字符匹配,查看对应位置的字符是否相等,或者删除前一个字符后查看是否相等,或者重复前面字符(指的是上一个位置的字符,而不是所有前面的字符中的任意一个)若干次后查看是否相等。为了方便分析,首先我们要对两个字符串的类型进行分类,字符串S是指只包含字母的普通字符串,字符串P指的是包含‘.’和‘*’的模式字符串。这两个字符串出现的情形可以分为以下四种。
1)两个字符串都为空,那么不用匹配了,两者是完全相等的,返回true。
2)如果字符串S不为空,字符串P为空,则字符串P不可能去匹配S。那S为空,P不为空呢,这个时候是有可能去匹配的,因为P中的字符可以增加或减少(当然是在有字符‘*’的情况下),所以是有可能的。也就是说S不为空,P为空就返回false,其他情况再论。
3)我们注意到字符‘*’很重要,可以增加或删除字符,因此在匹配的过程中可以以P中下一个要匹配的字符是否是‘*’来分。这里首先讲不是‘*’的情况。判断对应位置字符是否相等,或者如果不相等时P中的字符是否是‘.’(别忘了‘.’可以表示任意一个字符),如果字符对应相等或者P中字符是’.‘,则进行下一位判断(递归,S和P同步进行下一步),否则返回false。
4)这种情况当然就是P中当前匹配的字符的下一个字符是’*‘了。和3)一样,判断对应位置字符是否相等,或者如果不相等时P中的字符是否是‘.’,如果字符对应相等或者P中字符是’.‘,(这个时候要直接同步进入到下一位吗,不行啊,既然P中的字符下一个是’*‘,则下一个位置对应位字符肯定不相等),此时就要看P中的’*‘匹配几个前面的字符了,如果匹配0个,也就是说把前面的那个字符(即当前的字符)删除,’*‘的已经做了他的工作了,则P中的字符要往前跳2位(例如S为aba,P为ab*ba),而S中的字符位置不变。如果匹配一个以上呢,也就说,P中的字符’*‘至少可以充当一个字符,即在*前可以添加一个字符,需要添加吗,不需要,因为我们比较的是字符,虚拟添加的那个字符和当前P中的字符是一样的,所以我们只需要把S中的字符往前前进一步,P中的位置保持不变(但是效果和真的添加后P中的字符往前一步一样,)开始下一步的匹配,有人说这有可能匹配很多个字符后S到末尾了,而P还是’*‘,别往了’*‘有删除作用啊,可以直接跳过’*‘。 好了,这是当前字符可以匹配的情况(例如S为abbba,P为abxa)。当前字符如果不匹配呢,那就简单了,直接用’*‘把P中当前字符前面那个和S中不一样的字符删除,也就是说,S位置保持不变,P跳两步(例如S为acab,P为abxcab)。有人说为什么没有S跳一步,P保持不变这种情形呢,当前已经不相等了,S中跳一步默认S当前的字符是可以匹配的,这是错误的。
代码如下:
class Solution {
public:
bool isMatch(string s, string p) {
return match(s,p,0,0);
}
bool match(string& s,string& p,int is,int ip)
{
if(is==s.size()&&ip==p.size()){
return true;
}else if(is!=s.size()&&ip==p.size()){
return false;
}else{
if(ip+1==p.size()||p[ip+1]!='*'){
if(is!=s.size()&&(s[is]==p[ip]||p[ip]=='.')){
return match(s,p,is+1,ip+1);
}else{
return false;
}
}else {
if(is!=s.size()&&(s[is]==p[ip]||p[ip]=='.')){
return match(s,p,is,ip+2)|| match(s,p,is+1,ip);
}else{
return match(s,p,is,ip+2);
}
}
}
}
};