https://leetcode-cn.com/problems/regular-expression-matching/
解题思路
dp[0][0] = true; //主串前0个字符(空串) 和 模式串 前0个字符(空串) 能够匹配
for(int j = 2; j <= n; j++) {
if(p[j - 1] == '*' && j >= 2)
dp[0][j] = dp[0][j - 2]; //把主串当做空串的时候和模式串中带有*的比较,主要是由于*可以吃掉一部分主串 所以也有可能匹配上 比如空串 和 "a*b*c*"是匹配的
}
(一)当前字符匹配,或者模式字符是'.' : dp[i][j] = dp[i-1][j-1];
(二)当前模式字符是'*':
当前字符是p[j-1]='*',需要看其前一个字符p[j-2]与主字符s[i-1]是否匹配,前一个字符p[j-2] 是点或者 与主字符s[i-1]相等则匹配,否则不匹配。
(1)前一个字符p[j-2]与主字符s[i-1]匹配 : (去掉谁,谁就减, 减多少就看去掉了几个字符)
(1.1)则可以参考去掉模式串的值是否匹配,假如当前两个字符都是a, 也就是 去掉'a*'看是否匹配, 对应:
dp[i][j] = dp[i][j - 2];
(1.2)或者参考去掉当前主字符后是否匹配,即仅仅去掉当前主字符a, 对应 dp[i][j] = dp[i - 1][j];
(2)前一个字符p[j-2]与主字符s[i-1]不匹配 : 必须去掉模式串'a*'来作为dp[i][j], 即 dp[i][j] = dp[i][j - 2]。
代码:
bool isMatch(string s, string p) {
int m = s.length(), n = p.length();
bool dp[m + 1][n + 1];
memset(dp, false, sizeof(dp));
dp[0][0] = true; //主串前0个字符(空串) 和 模式串 前0个字符(空串) 能够匹配
for(int j = 2; j <= n; j++) {
if(p[j - 1] == '*' && j >= 2) dp[0][j] = dp[0][j - 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] == '*'){//(二)当前模式字符是'*'
//当前字符是p[j-1]='*',需要看其前一个字符p[j-2]与主字符s[i-1]是否匹配
bool flag = j >= 2 && (s[i - 1] == p[j - 2] || p[j - 2] == '.'); //前一个字符p[j-2] 是点或者 与主字符s[i-1]相等 则匹配
//(1)前一个字符p[j-2]与主字符s[i-1]匹配 : (去掉谁,谁就减, 减多少就看去掉了几个字符)
// (1.1)则可以参考去掉模式串的值是否匹配,假如当前两个字符都是a, 也就是 去掉'a*'看是否匹配 对应 dp[i][j] = flag && dp[i][j - 2];
// (1.2)或者参考去掉当前主字符后是否匹配,即仅仅去掉当前主字符a, 对应 dp[i][j] = flag && dp[i - 1][j];
//(2)前一个字符p[j-2]与主字符s[i-1]不匹配 : 必须去掉模式串'a*'来作为dp[i][j], 即 dp[i][j] = dp[i][j - 2]
dp[i][j] = flag && (dp[i][j - 2] || dp[i - 1][j]) || dp[i][j - 2];
}
}
}
return dp[m][n];
}