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
» Solve this problem
类似于Regular Expression Matching,此题可以采用搜索求解。
但是,在Regular Expression Matching中,"*"之前会指定一个字符,例如:"a*",而Wildcard Matching中的"*"可以匹配任意多的各种字符。
因此,Wildcard Matching的搜索量是大于Regular Expression Matching的。
搜索可以解决小数据,大数据是会超时的。
换一个思路,设数组F[i][j],表示到S串的第i位,P串的第j位是否匹配成功。
例如:
S="ababa",P="a*?",则
S/P | 0 'a' | 1 '*' | 2 '?' | 3 '/0' |
---|---|---|---|---|
0 'a' | TRUE | TRUE | FALSE | FALSE |
1 'b' | FALSE | TRUE | TRUE | FALSE |
2 'a' | FALSE | TRUE | TRUE | FALSE |
3 'b' | FALSE | TRUE | TRUE | FALSE |
4 'a' | FALSE | TRUE | TRUE | FALSE |
5 '/0' | FALSE | TRUE | TRUE | TRUE |
假设S的长度为Ls,P的长度为Lp,所求即为F[Ls, Lp]。
现在的关键问题在于,以及得到了F[i, j]如何推到之后的内容。
F[i, j] = true:
1.P[j] == '*', F[i + 1, j] = true
2.P[j + 1] = S[i + 1] || P[j + 1] == '?', F[i + 1, j + 1] = true
F[i, j] = false:
1.F[i + 1, j - 1] == true && P[j] == '*'
这样做提交之后,发现内存超出限制,测试的数据中S和P都非常长。
对空间作优化,可以看出F[i + 1][]只与F[i+1][]和F[i][]有关,与之前的F[i-1]、F[i-2]、F[i-3]、... 、F[0]都没有关系。
因此,可以只要F[i]和F[i+1]。
最终的代码:
class Solution {
public:
bool initCheck(const char *s, const char *p) {
int l1 = 0;
int idx = 0, l2 = 0;
while (s[l1] != '\0') {
l1++;
}
while (p[idx] != '\0') {
l2 += p[idx++] != '*' ? 1 : 0;
}
return l1 >= l2;
}
bool isMatch(const char *s, const char *p) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if (!initCheck(s, p)) {
return false;
}
int l = 0;
while (p[l++] != '\0');
bool prev[l], f[l];
memset(f, false, sizeof(bool) * l);
memset(prev, false, sizeof(bool) * l);
bool isFirst = true;
for (int i = 0; i < l; i++) {
if (p[i] == '*') {
f[i] = i == 0 || f[i - 1];
}
else if ((p[i] == '?' || p[i] == *s) && isFirst) {
isFirst = false;
f[i] = true;
}
else {
break;
}
}
s++;
while (*(s - 1) != '\0') {
memcpy(prev, f, l);
memset(f, false, sizeof(bool) * l);
for (int i = 0; i < l; i++) {
if (prev[i]) {
f[i] = f[i] || p[i] == '*';
f[i + 1] = f[i + 1] || p[i + 1] == '?' || p[i + 1] == *s;
}
else if (i == 0 || f[i - 1]) {
f[i] = f[i] || p[i] == '*';
}
}
s++;
}
return f[l - 1];
}
};