[Lc]10正则表达式匹配
Contents
题目
题解
1. 普通递归
class Solution {
public:
bool isMatch(string s, string p) {
if(p.empty()) return s.empty();//若p为空,则s为空返回false。否则返回true
//若s不为空且当前字符普配(s当前字符等于p当前字符,或者s当前字符等于.),nMatch为true
bool nMatch = !s.empty() && (p[0] == s[0] || p[0] == '.');
//讨论p为*的情况,若下一位为*
if(p[1] == '*'){
//则递归两种情况,
//1. 跳过p中的该字符与*号,即有0个该字符
//2. 与本字符匹配(nMatch),递归下一个s而p不变(*前的字符有可能多个)
return isMatch(s, p.substr(2)) ||
(nMatch && isMatch(s.substr(1), p));
}else{//若下一位不为*,挨个匹配递归
return nMatch && isMatch(s.substr(1), p.substr(1));
}
}
};
2. 记忆递归
自己写了半天老是溢出,这里是来自mecury的代码,用一个二维数组存储已经递归过的位置
class Solution {
public:
//记忆表
vector<vector<int>>memo;
bool isMatch(string s, string p) {
// 大小+1的目的是因为memo有边界限制,在递归出口是只判断了pi,但没有限制si
memo = vector<vector<int>>(s.size() + 1, vector<int>(p.size() + 1, -1));
return helper(0, 0, s, p);
}
bool helper(int si, int pi, string s, string p) {
//递归出口
//当si==s.size() 且 pi < p.size()时 可能p中还有“*”字符 可以令前面的字符出现0次以匹配s
if(pi == p.size()) {
return si == s.size();
}
//如果判断过了直接返回存储的结果
if(memo[si][pi] != -1) {
return memo[si][pi];
}
bool res = false; //整个结果是否匹配
bool cur_match = false; //当前字符是否匹配
if(si < s.size()) {
if(s[si] == p[pi] || p[pi] == '.') {
cur_match = true;
}
}
//判断下一个字符是否'*'
if((pi + 1) < p.size() && p[pi + 1] == '*') {
// 考虑只需两种情况:
// 情况1:当前字符出现0次:跳过pattern中的当前字符和下一个"*"==>helper(si, pi + 2, s, p)
// 情况2:当前字符出现1次:当前是否匹配 && 将字符s向后移动一位是否匹配==>cur_match && helper(si + 1, pi, s, p)
res = helper(si, pi + 2, s, p) || (cur_match && helper(si + 1, pi, s, p));
} else {
res = cur_match && helper(si + 1, pi + 1, s, p); //下一个不是"*"正常向后匹配就好
}
memo[si][pi] = res;
return res;
}
};
3. 动态规划
这题已经把我绕晕了,先放一放。动态规划的方法来自(https://leetcode.com/problems/regular-expression-matching/discuss/5684/c-on-space-dp)
We define dp[i][j] to be true if s[0..i) matches p[0..j) and false otherwise. The state equations will be:
dp[i][j] = dp[i - 1][j - 1], if p[j - 1] != ‘*’ && (s[i - 1] == p[j - 1] || p[j - 1] == ‘.');
dp[i][j] = dp[i][j - 2], if p[j - 1] == ‘*’ and the pattern repeats for 0 time;
dp[i][j] = dp[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == ‘.'), if p[j - 1] == ‘*’ and the pattern repeats for at least 1 time.
class Solution {
public:
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 i = 0; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (j > 1 && p[j - 1] == '*') {
dp[i][j] = dp[i][j - 2] || (i > 0 && (s[i - 1] == p[j - 2] || p[j - 2] == '.') && dp[i - 1][j]);
} else {
dp[i][j] = i > 0 && dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
}
}
}
return dp[m][n];
}
};
4. 正则匹配
class Solution {
public:
bool isMatch(string s, string p) {
return regex_match(s, regex(p));
}
};
Author ChrisHRZ
LastMod 2020-05-14