LeetCode 10. Regular Expression Matching
Given an input string s
and a pattern p
, implement regular expression matching with support for .
and *
where:
.
Matches any single character.*
Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Example 1:
Input: s = "aa", p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input: s = "aa", p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
method
dp[i][j]
:s
中以s[i-1]
结尾的子串与p
中以p[j-1]
结尾的子串是否匹配
- 如果
s[i-1]==p[j-1]
或者p[j-1]=='.'
(可以匹配任意字符),说明可以不用看这个字符,看前面的就行,所以dp[i][j] = dp[i-1][j-1]
- 否则,再看如果
p[j-1]=='*'
- 可以往前倒2个,就不看
p[j-2]
的字符和p[j-1]
的*
,如果dp[i][j-2]
为true
,dp[i][j]
也可以是true
,让p[j-2]
出现0次 - 如果
dp[i][j-2]
是false
,再看如果s[i-1]==p[j-2]
或者p[j-2]=='.'
,这样的话如果dp[i-1][j]
是true
,那dp[i][j]
也可以是true
,这样就是*
让前面的字符重复了一次
- 可以往前倒2个,就不看
第一行需要初始化,如果是*
,只能往前倒2个
× a b *
× 1 0 0 0
a 0 1 0 1(*让b重复0次)
b 0 0 1 1(*让b重复了1次)
b 0 0 0 1(*让b重复了2次)
可以这样理解,如果p[j-1]=='*'
,则dp[i][j] = dp[i][j-2] || dp[i-1][j]
,不过后面这个的前提是s[i-1]==p[j-2]
比如B
和BA*
是匹配的,现在要看BA
和BA*
是否匹配,因为s[i-1]=A
和p[j-2]=A
是匹配的,所有只要用*
让前面的A
再重复一次就可以了
bool isMatch(string s, string p) {
int m = s.size(), n = p.size();
vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
dp[0][0] = true;
for (int j = 2; j <= n; j++) {
if (p[j - 1] == '*')
dp[0][j] = dp[0][j - 2]; // 只能往前倒2个
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s[i - 1] == p[j - 1] || p[j - 1] == '.') {
dp[i][j] = dp[i - 1][j - 1];
}
else if (p[j - 1] == '*' && j >= 2) {// 因为要往前倒2个,保证不越界
if (dp[i][j - 2]) dp[i][j] = true; // 往前倒2个
else if (s[i - 1] == p[j - 2] || p[j - 2] == '.') {
dp[i][j] = dp[i - 1][j]; // 也可以从上面下来
}
}
}
}
return dp[m][n];
}