10. 正则表达式匹配
10. 正则表达式匹配
给你一个字符串 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
解释:".*" 表示可匹配零个或多个('*')任意字符('.')。
提示:
1 <= s.length <= 20
1 <= p.length <= 30
s
只包含从a-z
的小写字母。p
只包含从a-z
的小写字母,以及字符.
和*
。- 保证每次出现字符
*
时,前面都匹配到有效的字符
思路:
正则表达式匹配,经典的动态规划问题,在《剑指offer》中已经写过一次,这次再次遇到依然需要去看之前写过的题解,难免令人尴尬。还需要多加复习。
class Solution {
public:
//备忘录
map<string,bool>memo;
bool isMatch(string s, string p) {
//正则表达式经典动态规划问题
return dp(s,0,p,0);
}
//dp表示s[0...]和p[0...]是否能够匹配
bool dp(string s,int i,string p,int j){
//base case
if(j==p.size()){//如果p走完了,那么只要s也走完那么就匹配(注意:s走完了,p不一定走完)
if(i==s.size())return true;
}
if(i==s.size()){//s已经走完,但是p没有走完
//那么p要怎样才能走完呢?
//'x*'这样成对
if((p.size()-j)%2==1)return false;//如果剩下的元素数量不是偶数,就一定不符合规则
//如果是偶数就去看是不是'x*'形式
for(;j<p.size();j+=2){
if(p[j+1]!='*')return false;
}
return true;
}
//每次判断前看备忘录
string key=to_string(i)+','+to_string(j);
if(memo.count(key))return memo[key];
bool res=true;
//从i和j位置开始判断
//如果成功判断
if(s[i]==p[j]||p[j]=='.'){
//如果成功则还要去判断p的下一位是不是*,可以匹配0或n次
//如果匹配0次则直接跳过p的'.*',如果要匹配多次就继续去判断i+1,j不变 两者有一个成功就行
if(j<p.size()-1&&p[j+1]=='*'){
res=dp(s,i,p,j+2)||dp(s,i+1,p,j);
}else{
//如果没有*存在
res=dp(s,i+1,p,j+1);
}
}else{
//如果匹配失败 也有可能是j+1位是*,匹配0次
if(j<p.size()-1&&p[j+1]=='*')return dp(s,i,p,j+2);
else{
res=false;
}
}
//写到这里可以发现其实是存在重叠子问题的,那么我们可以记录s的i位置和p的j位置判断时的结果
memo[key]=res;//没有的话map会自己创建
return res;
}
};
本文来自博客园,作者:{BailanZ},转载请注明原文链接:https://www.cnblogs.com/BailanZ/p/16256571.html