题目:
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
'’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
题解
① 递归:
就是考虑每种情况情况
(每种情况写在注释里)
class Solution {
public:
string sss, ppp;
bool solve(int a, int b) {
// 避免最后 a 匹配完,b 还剩下 "a*b*c*",这种也算完全匹配
if(a == sss.size()) {
while(b < ppp.size() - 1) {
if(ppp[b + 1] == '*') {
b = b + 2;
}
else {
break;
}
}
}
// 递归终止条件,如果都到了字符串末尾,则完全匹配
if(a == sss.size() && b == ppp.size()) {
return true;
}
// 递归终止条件,如果其中一个到了字符串末尾,另一个没到末尾,则不是完全匹配
if((a == sss.size() || b == ppp.size()) && (a + b != sss.size() + ppp.size())) {
return false;
}
// 如果该字符后面有 '*'
if(b < ppp.size() - 1 && ppp[b + 1] == '*') {
// 如果有重复的 "a*a*a*",只用看作一个 'a*',特别的如果存在 '*',例 "a*.*",可以看成 ".*"
if(b < ppp.size() - 3 && ppp[b + 3] == '*') {
if(ppp[b + 2] == '.' || ppp[b + 2] == ppp[b]) {
return solve(a, b + 2);
}
}
// 如果字符相同,则可以选择不匹配,或者匹配
if(sss[a] == ppp[b] || ppp[b] == '.') {
return solve(a + 1, b) || solve(a, b + 2);
}
// 如果字符不相同,则只能跳过,并且得跳过两个 '*' 也要被跳过
else {
return solve(a, b + 2);
}
}
// 如果该字符后面没有 '*'
else {
// 如果相同则匹配
if(sss[a] == ppp[b] || ppp[b] == '.') {
return solve(a + 1, b + 1);
}
// 如果不相同则不匹配
else {
return false;
}
}
}
bool isMatch(string s, string p) {
sss = s;
ppp = p;
// 从两个字符串的开头开始进行匹配
return solve(0, 0);
}
};
② dp
定义一个数组 dp[i][j],代表 p 字符串前 i 个 和 s 字符串前 j 个是否匹配
首先 dp[0][0] 肯定是匹配的,特别的,类似 “aa” 也和 “” 是匹配的,所以预处理时我们需要考虑
接下来就类似于递归,考虑每种情况
class Solution {
public:
bool dp[35][35];
bool isMatch(string s, string p) {
dp[0][0] = true;
int f = 2;
while(f <= p.size()) {
if(p[f - 1] == '*') {
dp[f][0] = true;
}
else {
break;
}
f = f + 2;
}
for(int i = 1; i <= p.size(); i++) {
for(int j = 1; j <= s.size(); j++) {
if(p[i - 1] == '*') {
dp[i][j] = dp[i - 1][j];
}
else if(i < p.size() && p[i] == '*') {
if(p[i - 1] == s[j - 1] || p[i - 1] == '.') {
dp[i][j] = (dp[i - 1][j - 1] || dp[i - 1][j] || dp[i][j - 1]);
}
else {
dp[i][j] = dp[i-1][j];
}
}
else if(p[i - 1] == s[j - 1] || p[i - 1] == '.') {
dp[i][j] = dp[i - 1][j - 1];
}
else {
dp[i][j] = false;
}
}
}
return dp[p.size()][s.size()];
}
};