Problem 10 - Regular Expression Matching - 正则表达式匹配¶
2022.01.19
给你一个字符串
s
和一个字符规律p
,请你来实现一个支持'.'
和'*'
的正则表达式匹配。
'.'
匹配任意单个字符'*'
匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串
s
的,而不是部分字符串。
输入:s = "aab" p = "c*a*b"
输出:true
解释:因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
动态规划¶
状态:
f[i][j]
表示 s
的前 i
个 字符与 p
的前 j
个字符能否匹配。
状态转移:
考虑 p[j]
是否等于这个能匹配任意多字符的 *
。
若 p[j] != '*'
,则只能在 s
中匹配一个字符。那么,当 match(s[i], p[j]) == true
时,f[i][j]
可以由 f[i - 1][j - 1]
转移过来;若不成立,则没有这条转移关系。
若 p[j] == '*'
,则我们实际上只有两种情况:
- 当
s[i]
可以和p[i - 1]
p[i]
这个整体匹配时,匹配s[i]
,这时f[i][j]
可以由f[i - 1][j]
转移; - 不匹配
s[i]
,这时相当于直接把p[j - 1]
和p[j]
丢掉,f[i][j]
可以由f[i][j - 2]
转移。
初始值:
f[0][0] = true
,同时要记得初始 f[0][j]
。
class Solution {
public:
bool isMatch(string s, string p) {
s = " " + s;
p = " " + p;
static bool f[21][31];
memset(f, 0, sizeof(f));
f[0][0] = 1;
for (int j = 1; j < p.length(); j++) {
if (p[j] == '*')
f[0][j] |= f[0][j - 2];
}
for (int i = 1; i < s.length(); i++) {
for (int j = 1; j < p.length(); j++) {
if (p[j] != '*' ) {
if (s[i] == p[j] || p[j] == '.')
f[i][j] |= f[i - 1][j - 1];
}
else {
if (s[i] == p[j - 1] || p[j - 1] == '.') {
f[i][j] |= f[i - 1][j];
f[i][j] |= f[i][j - 2];
}
else f[i][j] |= f[i][j - 2];
}
// cout << "f[" << i << "][" << j << "] = " << f[i][j] << endl;
}
}
return f[s.length() - 1][p.length() - 1];
}
};
DFS¶
搜索过程中,枚举 *
可以匹配多少个字符即可。