leetcode:Wildcard Matching
题目
链接:https://oj.leetcode.com/problems/wildcard-matching/
描述:寻找一种字符串的匹配模式,匹配规则:
1. '?'可以匹配任意一个字符;
2. '*'可以匹配任意字符串,可以匹配空串。
例子:
isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "*") → true isMatch("aa", "a*") → true isMatch("ab", "?*") → true isMatch("aab", "c*a*b") → false
思路
从左到右字符一个一个匹配,这里难的是关于'*'的匹配,其他都还好,注意到如果一个字符串A+B(A是一个字符串,B是另一个)匹配字符串*+B,那么任何A的尾巴+B 都应该是可以匹配到*+B的,所以可以产生一种递归。如果当前字符遇到*,那么它后面知道真正于模式匹配的那个字符之前都是可以匹配当前模式的,所以可以递归调用isMatch(s+1,p)得到的结果应该是和isMatch(s,p)相同的,如果不同就可以返回false,也就是不匹配。
递归代码(TLM)
使用递归的方法可以写出下面代码。
bool isMatch(const char * s, const char * p)
{
while(*s != '\0' && *p != '\0')
{
cout<<"Here! "<<s<<", "<<p<<endl;
if (*s == *p || *p == '?')
{
s++;p++;
}
if (*p == '*')
{
while(*p == '*' || *p == '?') p++;
if (*p == '\0')
{
return true;
}
while(*s != '\0')
{
while(*s != '\0' && *s != *p) s++; //将所有可以匹配到下一个字符串的字符串都遍历一遍,如果都不符合就false
if (isMatch( ++s,p + 1))
{
return true;
}
}
return false;
}
if (*s != *p)
{
return false;
}
}
if (*s != '\0')
{
return false;
}
while(*p != '\0' && *p == '*')p++;
if (*p != '\0')
{
return false;
}
return true;
}
迭代代码
这种递归深度太深,所以肯定会超时,所以必须优化,剔除那些重复的操作,不用递归。
采用迭代的思想,首先,正常匹配所有其他非*字符,等遇到*记录*出现,今后遇到不匹配的可以使用*号抵消,一直将遇到*之后的不和模式匹配的字符都抵消掉,,一直到最终整个字符串都遍历完毕,如果模式串,也同样只剩下*,那么就匹配成功,如果不能将模式串完全用尽,那么就是false。代码如下
bool isMatch(const char * s, const char * p)
{
bool flag = false;
const char * pstr;
const char * sstr;
while(*s != '\0')
{
//cout<<"Here! "<<s<<", "<<p<<endl;
if (*s == *p || *p == '?')
{
s++;p++;
}
else if (*p == '*')
{
flag = true;
pstr = p;
sstr = s;
while(*pstr == '*') pstr++;
if (*pstr == '\0')
{
return true;
}
p = pstr;
}
else if (*s != *p )
{
if(!flag) return false;
sstr++;
s = sstr;
p = pstr;
}
}
if (*s != '\0')
{
return false;
}
while(*p != '\0' && *p == '*')p++;
if (*p != '\0')
{
return false;
}
return true;
}
代码参考了github上一位大牛的思路。