传送门:https://leetcode-cn.com/problems/regular-expression-matching/
题目
给你一个字符串
s
和一个字符规律p
,请你来实现一个支持'.'
和'*'
的正则表达式匹配。
'.'
:匹配任意单个字符'*'
:匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖整个字符串s
的,而不是部分字符串。
示例 1:
输入:s = “aa” p = “a” 输出:false 解释:”a” 无法匹配 “aa” 整个字符串。
示例 2:**
输入:s = “aa” p = “a“ 输出:true 解释:因为 ‘‘ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
示例 3:**
输入:s = “ab” p = “.“ 输出:true 解释:”.“ 表示可匹配零个或多个(’*’)任意字符(’.’)。
示例 4:**
输入:s = “aab” p = “cab” 输出:true 解释:因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
示例 5:
输入:s = “mississippi” p = “misisp*.” 输出:false
阿巴阿巴 ….大家好,我是老实巴交的老实人,得知大家都用动态规划做的我人傻了。
代码
我的代码
class Solution {
public:
bool clearOne(string p) {//空串返回false
int p_len = p.length();
int pp = 0;
if (p.empty() || p == "")return false;
if (((pp + 1) < p.length()) && (p.at(pp + 1) == '*')) return true;
return false;
}
bool check_pnull(string p) {//判断规则p剩余部分是否可以抵消
int p_len = p.length();
int pp = 0;
if (p.empty() || p == "")return true;
while (pp < p_len) {//字母在
if (pp + 1 < p_len) {//*号在
if (p.at(pp + 1) == '*')//*匹配
pp += 2;
else
return false;
}
else {//*号不在
if (p.at(pp) == '*')
return true;
return false;
}
}
return true;
}
bool isMatch(string s, string p) {
int s_len = s.length();
int p_len = p.length();//二者长度
int sp, pp;//哨兵
sp = pp = 0;//初始化
if ((!s.empty()) && (p.empty() || p == ""))return false;
if (!p.empty() && (s.empty() || s == "")) {
if (check_pnull(p))return true;
return false;
}//去除非法情况和特殊空串情况
while (sp < s_len || pp < p_len) {
while ((sp < s_len && pp < p_len) && s.at(sp) == p.at(pp)) {//二者相等就顺着排
sp++; pp++;
}//匹配就下行
//出来有可能是不匹配也有可能是超过长度
//1不匹配
if (sp < s_len && pp < p_len) {//确保在长度内
if (p.at(pp) == '.') {//.类型不匹配
sp++; pp++;
}
else if (p.at(pp) == '*') {//*类型不匹配
bool real = false;
int temp_sp = sp - 1;
//第一种先消去*前面的来跟s匹配
if (pp + 1 < p_len)//未越界情况才有可能消去,越界一定不用消除
real= isMatch(s.substr(temp_sp, s_len - temp_sp), p.substr(pp + 1, p_len - pp - 1));
if (real)return true;
//第二种到底匹配几个的问题
if ((sp < s_len && pp + 1 < p_len)) {//*只匹配一次
real = isMatch(s.substr(sp, s_len - sp), p.substr(pp + 1, p_len - pp - 1));
if (real)return true;
}
while ((sp < s_len && pp < p_len)) {//从第2此开始依次匹配
if ((s.at(sp) == p.at(pp - 1)) || p.at(pp - 1) == '.') {
sp++;
if ((sp < s_len && pp + 1 < p_len)) {
real = isMatch(s.substr(sp, s_len - sp), p.substr(pp + 1, p_len - pp - 1));
if (real)return true;
}
}
else {
pp++;
break;
}
}
// pp++;
}
else {
if ((pp + 1 < p_len) && (p.at(pp + 1) == '*')) {//还有救
pp += 2;
}
else
return false;
}
}
else {//2超出长度
//如果二者同时超出了长度则说明匹配成功
//若是单独一方超出则要看情况
//a. 若p超出了长度,说明s串还有未比配的数,一定不匹配
//b. 若s超出了长度,说明要回溯,两种检查,剩下p是否能check_pnull,若能则匹配,若不能则claenOne弄掉一对让s的最后一个字母与剩下的p规则匹配
if (sp == s_len && pp == p_len) {//二者同时超出了长度则说明匹配成功
return true;
}
else {//单独一方超出
if (pp >= p_len)return false;//a
if (sp >= s_len) {//b
if (p.at(pp) == '*') {
if (check_pnull(p.substr(pp + 1, p_len - pp))) return true;//剩下的能消除
else {//不能消除
if (clearOne(p.substr(pp - 1, p_len - pp + 1))) {
sp--;
pp = pp + 1;
return isMatch(s.substr(sp, s_len - sp), p.substr(pp, p_len - pp));
}
else return false;
}
}
else {
if (check_pnull(p.substr(pp, p_len - pp))) return true;//剩下的能消除
else {//不能消除
if (clearOne(p.substr(pp - 1, p_len - pp + 1))) {
sp--;
pp = pp + 1;
return isMatch(s.substr(sp, s_len - sp), p.substr(pp, p_len - pp));
}
else return false;
}
}
}
}
}
}
if (sp == s_len && pp == p_len)
return true;
else
return false;
}
};