正则表达式匹配
总算有一道是没看题解写出来的了…但是还是偷偷瞄了一眼知道这是一道dp以及想了好久好久…所以还是放到丢人日记里
我们用状态
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]来表示串s的第i位与串p的第j位是否能匹配,那么对于串p存在的三种情况:
‘.’匹配任意字符:直接匹配,状态方程:
dp[i + 1][j + 1] |= dp[i][j]
'a’普通字符:检查能否匹配,状态方程:
dp[i + 1][j + 1] |= dp[i][j] && s[i] == p[j]
然后就是比较麻烦的’*'字符了,分以下几种情况:
- 忽略这个’*'字符,状态方程:
dp[i][j + 1] |= dp[i][j]
- 忽略这个’*'字符以及前一个字符,状态方程:
dp[i][j + 1] |= dp[i][j - 1]
- 匹配这个字符,状态方程:
dp[i + 1][j] = dp[i][j] && (s[i] == p[j - 1] || p[j - 1] == '.')
因为转移只和前一项有关,所以可以用滚动的方式将前一维省去。
对了,字符串最后需要加上一个无关字符来使得能处理掉尾巴上的’*’
代码:
class Solution {
public:
bool isMatch(string s, string p) {
s += '$';
int n = s.length(), m = p.length();
vector<vector<bool> >dp(2);
for (int i = 0; i < 2; i++)
for (int j = 0; j < m + 1; j++) dp[i].push_back(0);
dp[0][0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m + 1; j++) dp[(i + 1) & 1][j] = 0;
for (int j = 0; j < m; j++) {
if (p[j] == '.') {
dp[(i + 1) & 1][j + 1] |= dp[i & 1][j];
}
else if (p[j] == '*') {
dp[i & 1][j + 1] |= dp[i & 1][j];
dp[i & 1][j + 1] |= dp[i & 1][j - 1];
dp[(i + 1) & 1][j] |= dp[i & 1][j] && (s[i] == p[j - 1] || p[j - 1] == '.');
}
else {
dp[(i + 1) & 1][j + 1] |= dp[i & 1][j] && s[i] == p[j];
}
}
}
return dp[(n - 1) & 1][m];
}
};