44. Wildcard Matching
题目链接:44. Wildcard Matching
题意
实现通配符?和*,?匹配任意单个字符,*匹配任意字符串,包括空串。题目与 10. Regular Expression Matching很相似,连测试样例都是一样的, 第10题链接,不同之处在于:第10题中*只能匹配0个或多个它前面的字符,像”aaaa”,而本题中*可匹配任意字符串,也就是说像”abcdefg”这种字符串也能匹配。
解法
match[i][j]表示字符串s从0到i-1的子串能否与模式p从0到j-1的子串匹配
状态转移:
- 当p[j-1]不是星号时,在确保s[i-1]==p[j-1]的情况下可以转移到子问题match[i-1][j-1],
当p[j-1]是星号时,由于星号可以匹配任意字符串,所以可能有三种情况
- 星号匹配到0个字符,此时转移到子问题match[i][j-1],注意这里j-1而不是第10题中的-2,因为本题中的星号独立于它前面的字符
- 星号匹配到一个字符,此时转移到子问题match[i-1][j-1]
- 星号匹配到多个字符,此时是否匹配取决于与s[0~i-2]子串能否匹配,转移到子问题match[i-1][j],跟第10题一样,这里j不变,因星号要继续匹配字符
match[i][j]=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪true,false,true,match[i][j−1]||match[i−1][j−1]||match[i−1][j],s[i−1]==p[j−1]并且match[i−1][j−1],i==0并且j==0(空模式匹配空字符串)j==0并且i>0(空模式不匹配非空字符串)i==0并且对于所有k<=j,p[k−1]==′∗′p[j−1]==′.′其他
返回match[m][n],m、n分别是字符串和模式的长度。
代码
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Solution {
public:
bool isMatch(string s, string p) {
int m = s.length();//row
int n = p.length();//col
vector<vector<bool> > match(m+1, vector<bool>(n+1, false));
match[0][0] = true;//empty pattern matches empty string
//nonempty pattern matching empty string
for (int j = 1; j <= n; ++j) {
if (p[j - 1] != '*')
break;
match[0][j] = true;
}
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (p[j - 1] == '?') {
match[i][j] = match[i - 1][j - 1];
}
else if (p[j - 1] == '*') {
match[i][j] = match[i][j - 1] || match[i-1][j-1] || match[i-1][j];
}
else {
match[i][j] = (s[i - 1] == p[j - 1] && match[i - 1][j - 1]);
}
}
}
return match[m][n];
}
};
算法复杂度
算法复杂度为O(nm)。
注意
第四种情况,由于不确定*应该匹配多少字符,所以对所有可能情况取并,match[k][j-1]表示*匹配了i-k个字符