这一题从前往后事实上是很难找到办法解决的,当正面无法解决问题时我们不妨换一个角度思考,从后往前匹配。
先来个大概的思路:当当前位置字符一样,显然最后是否能匹配取决于前面位置能否能匹配,所以要考虑前面位置是否匹配,而前面位置是否匹配,取决于那个位置值是否匹配(相同?. 等)和那个位置前面的值是否匹配。不难看出,这有点像反递推。
接下来我们来考虑细的思路 :
当往前推超出了界限,我们需要特判。
当一个结束另一个未结束也需要特判。
若两个都未结束:
若两个相等,取决于当前位置的前一个位置是否能匹配
若是 ‘.’ ,则默认这个位置匹配了,跟上面是一样的行为
若是 ‘*’ ,那么这个可以匹配 星号 前面字符0次,1次或者多次。只要有一种情况匹配上了都认为可以匹配上。匹配0次时是否能匹配,则取决于模式串前两位和待匹配串当前位是否能匹配。匹配1次,则情况变成了判断模式串前一位(星号以前的那个字符)是否能与待匹配串的当前位匹配。匹配一次以上也是类似的情况,直接继续往前递推即可。
class Solution {
public:
bool IsAlpha(char c)
{
if(c >= 'a' && c <='z')
return true;
return false;
}
int AllStar(string &p,int k)
{
int temp = 0;
for(;k < p.length();++k)
if(p[k] != '*')
return 1;
return temp;
}
bool Match(string &s,string &p,int i1,int i2)
{
if(i1 < 0)
{
if(i2 < 0)
return true;
if(p[i2] != '*')
return false;
//如果i2还不等于0,那么判断前面是不是都是 字符*字符*...
return Match(s,p,i1,i2-2);//是*,则跳过它控制的字符继续判断
}
else if(i2 < 0)//i2结束了,但是l1还存在字符未匹配
return false;
//从后往前匹配,若是字母
if(IsAlpha(p[i2]))
{
if(s[i1]!=p[i2])
return false;
else
return Match(s,p,i1-1,i2-1);
}
else if(p[i2] == '.')
return Match(s,p,i1-1,i2-1);
else if(p[i2] == '*')//匹配前面的字符一次或者多次
{
//可匹配前面字符0次,或者1次,或者多次
// Match(s,p,i1,i2-2)//匹配0次
// Match(s,p,i1,i2-1)//匹配1次
// Match(s,p,i1-1,i2)//匹配多次
//若*号前面没有字符
if(i2-1 < 0)
return false;
//匹配0次则无需管字符是不是对的,若匹配多次则需要判断字符是否正确
//字符相同或者是.都算
return Match(s,p,i1,i2-2)||((s[i1] == p[i2-1] || p[i2-1] == '.') && Match(s,p,i1,i2-1))||((s[i1] == p[i2-1] || p[i2-1] == '.')&&Match(s,p,i1-1,i2));
}
return true;
}
bool isMatch(string s, string p) {
//.匹配任意字符
//*匹配前者0次或者多次
//s只含小写字母
//p只含小写字母和.*
return Match(s,p,s.length()-1,p.length()-1);
}
};