Wildcard Matching
Implement wildcard pattern matching with support for
'?'
and
'*'
.
'?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(const char *s, const char *p) Some examples: 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
思路:
应该可以用动态规划的方法来处理。
题解:
class Solution {
public:
bool isMatch (const char* s, const char* p)
{
if (s == 0 || p == 0) return false;
while (true)
{
if (*s == 0 && *p == 0) return true;
if (*p == 0) return false;
if (*p == '?' || *p == *s)
{
++s, ++p;
}
else if (*p == '*')
{
const char* next_p = p + 1;
while (*next_p == '*' && *next_p != 0) ++next_p;
if (*s == 0)
return *next_p == 0;
else
{
if (*next_p == '?')
return isMatch (s, next_p) || isMatch (s + 1, p);
else if (*next_p != 0)
{
const char* next_s = s;
bool valid = false;
while (*next_s != 0)
{
if (*next_s == *next_p && isMatch (next_s + 1, next_p + 1))
{
valid = true;
break;
}
++next_s;
}
return valid;
}
else
return true;
}
}
else
return false;
}
}
};
思路:
上述方法是超时的。没有办法。不过考虑到其实可以把pattern以*为间隔分块,然后在字符串里看是否这些块按顺序出现,当然开头和结尾的部分要特殊处理一下。比如结尾的块不是'*',那么就必须按照倒序检查原始字符串末尾的字符。
题解:
class Solution {
public:
#define charMatch(s, p) (p == '?' || p == s)
int subStr (const char* s, int start, const char* p, int len)
{
while (s[start] != 0)
{
if (charMatch (s[start], p[0]))
{
bool match = true;
for (int j = 1; j < len; ++j)
if (s[start + j] == 0)
return -1;
else if (!charMatch (s[start + j], p[j]))
{
match = false;
break;
}
if (match)
return start + len;
}
++start;
}
return -1;
}
#undef charMatch
bool isMatch (const char* s, const char* p)
{
bool front_vary = *p == '*';
bool back_vary = false;
int s_offset = 0;
int p_start = 0;
int p_offset = 0;
while (p[p_offset] != 0)
{
p_start = p_offset;
while (p[p_start] == '*' && p[p_start] != 0) ++p_start;
if (p[p_start] == 0)
{
// is pattern empty?
if (p_start != 0)
back_vary = p[p_start - 1] == '*';
break;
}
p_offset = p_start + 1;
while (p[p_offset] != '*' && p[p_offset] != 0) ++p_offset;
if (p[p_offset] == 0 && p_start != 0)
{
// for the last block we need to do matching backwards
int old_soffset = s_offset;
while (s[s_offset] != 0) ++s_offset;
int pi = p_offset;
int si = s_offset;
while(pi >= p_start && si >= old_soffset)
{
if (p[pi] != '?' && p[pi] != s[si])
return false;
--pi, --si;
}
if (pi >= p_start)
return false; // s does not have enough space
}
else
{
s_offset = subStr (s, s_offset, p + p_start, p_offset - p_start);
if (s_offset == -1 || (p_start == 0 && !front_vary && s_offset != p_offset - p_start))
return false;
}
}
if (!back_vary && s[s_offset] != 0)
return false;
else
return true;
}
};