题目:
Given an input string (s
) and a pattern (p
), 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).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like?
or*
.
Example 1:
Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input:
s = "aa"
p = "*"
Output: true
Explanation: '*' matches any sequence.
Example 3:
Input:
s = "cb"
p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
Example 4:
Input:
s = "adceb"
p = "*a*b"
Output: true
Explanation: The first '*' matches the empty sequence, while the second '*' matches the substring "dce".
Example 5:
Input:
s = "acdcb"
p = "a*c?b"
Output: false
描述:
给出一个字符串和一个模式串,判断模式串是否能匹配所给字符串,其中:
? 能匹配任意单个字符,* 能匹配任意长度的字符串(包含空串)
分析:
除了递归,想不到别的方法,错了很多次以后,调通了,但是却是超时.....(见代码一)
实在是想不到解法了,学习别人的思路吧
线性时间的题解的做法是:(见代码二)
将所有的 * 先视为不存在,然后进行两串匹配,若某个位置匹配失败,则尝试利用距离当前失配位置最近的一个 * 去匹配失配的主串元素,即从主串中下一个能和模式串中当前位置匹配的位置开始匹配,若匹配成功,则返回true,若匹配失败,则再选择稍后位置中下一个能和 * 后元素匹配的位置进行匹配,直到程序结束。
测试数据:(有点多...)
"abbabaaabbabbaababbabbbbbabbbabbbabaaaaababababbbabababaabbababaabbbbbbaaaabababbbaabbbbaabbbbababababbaabbaababaabbbababababbbbaaabbbbbabaaaabbababbbbaababaabbababbbbbababbbabaaaaaaaabbbbbaabaaababaaaabb"
"**aa*****ba*a*bb**aa*ab****a*aaaaaa***a*aaaa**bbabb*b*b**aaaaaaaaa*a********ba*bbb***a*ba*bb*bb**a*b*bb"
"aaabbbaabaaaaababaabaaabbabbbbbbbbaabababbabbbaaaaba"
"a*******b"
"c"
"*c?*"
"b"
"?*?"
"ho"
"ho**"
"acdcb"
"a*c?b"
"c"
"*?*"
"c"
"**c*"
""
"*"
"aa"
"**a"
""
""
"a"
""
""
"?"
"aa"
"*"
"abceb"
"*a*b"
"cb"
"?a"
"a"
"?"
"aa"
"a"
"cb"
"?b"
代码一:(暴力递归,超时)
class Solution {
public:
bool isMatch(string s, string p) {
p = compress(p);
return tryMatch(s, p , 0, 0);
}
string compress(const string &p) {
string result;
for (int i = 0; i < p.size(); ++ i) {
if (result.size() && result[result.size() - 1] == '*' && p[i] == '*') {
continue;
}
result.push_back(p[i]);
}
return result;
}
bool tryMatch(const string &s, const string &p, int i, int j) {
while (i < s.size() && j < p.size()) {
if (s[i] == p[j] || p[j] == '?') {
++ i;
++ j;//匹配成功
} else if (p[j] == '*') {
return tryMatchStar(s, p, i, j + 1);
} else {
return false;
}
}
if (i == s.size()) {
return allStar(p, j);
}
return j != p.size();
}
bool tryMatchStar(const string &s, const string &p, int i, int j) {
if (j == p.size()) {//*后边没有任何元素,必定匹配成功
return true;
}
while (i < s.size()) {
if (p[j] == '*' && tryMatchStar(s, p, i, j + 1)) {
return true;
} else if ((p[j] == '?' || s[i] == p[j]) && tryMatch(s, p, i, j)) {
return true;
}
++ i;
}
return allStar(p, j);
}
bool allStar(const string &p, int index) {
for (int i = index; i < p.size(); ++ i) {
if (p[i] != '*') {
return false;
}
}
return true;
}
};
代码二: (时间复杂度 O ( n + m),n,m 分别为两个串的长度)
class Solution {
public:
bool isMatch(string s, string p) {
int i = 0, j = 0, star = -1, current = 0;
while (i < s.size()) {
if (s[i] == p[j] || p[j] == '?') {
++ i;
++ j;
} else if (p[j] == '*') {
star = j;
current = i;
++ j;
} else if (star != -1) {//匹配失败但星号存在
i = current + 1;
j = star + 1;
++ current;
} else {
break;
}
}
return i == s.size() && allStar(p, j);
}
bool allStar(const string &p, int index) {
for (int i = index; i < p.size(); ++ i) {
if (p[i] != '*') {
return false;
}
}
return true;
}
};