class Solution {
public:
bool isMatch(string s, string p) {
int m = s.size();
int n = p.size();
auto matches = [&](int i, int j) {
if (i == 0) {
return false;
}
if (p[j - 1] == '.') {
return true;
}
return s[i - 1] == p[j - 1];
};
vector<vector<int>> f(m + 1, vector<int>(n + 1));
f[0][0] = true;
for (int i = 0; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (p[j - 1] == '*') {
f[i][j] |= f[i][j - 2];
if (matches(i, j - 1)) {
f[i][j] |= f[i - 1][j];
}
}
else {
if (matches(i, j)) {
f[i][j] |= f[i - 1][j - 1];
}
}
}
}
return f[m][n];
}
};
matches
函数是一个辅助函数,用于判断字符串s
的第i
个字符是否与模式p
的第j
个字符匹配。如果模式中的字符是'.'
,则它可以匹配任何字符;如果模式中的字符是'*'
,则matches
函数返回false
,因为'*'
不能直接与字符串中的字符匹配。
f
是一个二维向量,用于存储动态规划的状态。f[i][j]
表示s
的前i
个字符是否可以与p
的前j
个字符匹配。初始时,f[0][0]
设置为true
,表示两个空字符串是可以匹配的。接下来,代码使用两层循环遍历字符串
s
和模式p
。对于每个状态(i, j)
,代码根据模式p
的第j
个字符进行判断:
如果模式中的字符是
'*'
,则有两种情况:一种是'*'
表示0个前面的字符,这时状态转移方程为f[i][j] |= f[i][j - 2]
;另一种是'*'
表示至少1个前面的字符,这时状态转移方程为f[i][j] |= f[i - 1][j]
。这两种情况是逻辑或的关系,所以使用了|=
操作符。如果模式中的字符不是
'*'
,则只有一种情况:如果s
的第i
个字符与p
的第j
个字符匹配,则状态转移方程为f[i][j] |= f[i - 1][j - 1]
。最后,函数返回
f[m][n]
,即字符串s
的全部字符是否可以与模式p
的全部字符匹配。这个实现使用了动态规划的思想,时间复杂度为
O(mn)
,其中m
和n
分别是字符串s
和模式p
的长度。