正则表达式匹配
状态转移方程:
f[i][j]
表示从s串下标为i之后 与 p串下标为j之后是否匹配
- 第一种情况
p[j+1]
不为'*'
:字符匹配(包括字符相同和p串此处字符为'.'
- 则
f[i][j] = f[i + 1][j + 1] && (s[i] == p[j] || p[j] == '.')
- 则
- 第二种情况
p[j+1]
为'*'
:- 则
(f[i+1][j] && f[i] == f[j]) || f[i][j+2])
- 则
class Solution {
public:
vector<vector><int>> f;
int n, m;
bool isMatch(string s, string p) {
n = s.size();
m = p.size();
f = vector<vector><int>>(n + 1, vector<int>(m + 1, -1));
return dp(0, 0, s, p);
}
bool dp(int i, int j, s, p) {
if (f[i][j] != -1) return f[i][j];
if (j == m) return f[i][j] = i == n;
bool match = i < n && (s[i] == p[j] || p[j] == '.');
bool ans;
if (j + 1 < m && p[j + 1] != '*')
ans = dp(i+1, j+1, s, p) && match;
else {
ans = dp(i, j + 2, s, p) || (match && dp(i+1, j, s, p));
}
return f[i][j] = ans;
}
};
比较容易理解的方式
状态转移方程f[i][j]表示前s的前i个与p的前j个相匹配
- p串第
j
个位置不为'*'
:f[i][j] = f[i - 1][j - 1] && s[i] == p[j] || p[j] == '.'
- p串第
j
个位置为'*'
:- 如果
'*'
在此是让它前面的字符出现零次 则有:f[i][j] = f[i][j-2]
- 如果是让前面的字符出现多次 则有:
f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.');
- 如果
代码如下:
bool isMatch(string s, string p) {
s = " " + s, p = " " + p;
int n = s.size(), m = p.size();
vector<vector<bool>> f(n+1, vector<bool>(m+1, false));
int i = 0, j = 0;
f[0][0] = true; //两个串都为空,满足条件
for (int i = 0; i < s.size(); i++) {
for (int j = 1; j < p.size(); j++) {
if (j + 1 < p.size() && p[j + 1] == '*') continue; //当前位应该和下一位看作整体;
if (i && p[j] != '*') {
f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '.');
} else if (p[j] == '*') {
f[i][j] = f[i][j - 2] || i && f[i - 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.');
}
}
}
}