给定一个字符串 (s
) 和一个字符模式 (p
)。实现支持 '.'
和 '*'
的正则表达式匹配。
'.' 匹配任意单个字符。 '*' 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s
) ,而不是部分字符串。
说明:
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母,以及字符.
和*
。
示例 1:
输入: s = "aa" p = "a" 输出: false 解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入: s = "aa" p = "a*" 输出: true 解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。
示例 3:
输入: s = "ab" p = ".*" 输出: true 解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入: s = "aab" p = "c*a*b" 输出: true 解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入: s = "mississippi" p = "mis*is*p*." 输出: false
答主最初受编译原理课影响,不自觉得想用编译原理中得东西解决问题,理论上是可以解决,但效率没有dp快,且实现较为复杂。
注释部分为得到每个字符的可能后缀,未测试
解答如下(思路写在注释里了):
class Solution {
public:
// //用邻接表存储后缀下标,用-1表示当前已经可以结束
// map<int,vector<int>> preDeal(string p){
// map<int,vector<int>> suffix;
// for(int i=p.length()-1;i>=-1;i--){
// if(p[i]!='*'){
// vector<int> sf;
// if(i+1>=p.length()){
// //当末尾为字母包含1表示可以结束
// sf.insert(sf.begin(),-1);
// }else {
// int gap=0;
// if(p[i+1]=='*'){
// //如a*,应当首先包含自身
// gap=1;
// }
// //默认不出现形如a**类似意义的字符
// if(i+gap+1>=p.length()){
// //若a*后面为空,应当包含结束标志
// sf.insert(sf.begin(),-1);
// }else{
// if(i+gap+2<p.length()&&p[i+gap+2]=='*'){
// //形如a*b*,当 b后的*存在时,b的后缀也是a的后缀
// sf.insert(sf.end(),suffix[i+gap+1].begin(),suffix[i+gap+1].end());
// }else{
// //形如a*bb,其后缀为a的后缀为a,及b本身
// sf.insert(sf.end(),i+gap+1);
// }
// }
// //将循环自身放在最后,先尝试其他情况能否成功
// if(gap==1){
// sf.insert(sf.end(),i);
// }
// }
// //将后缀添加到邻接表中
// suffix[i]=sf;
// }
// }
// return suffix;
// }
bool isMatch(string s, string p) {
bool ss[200][200];
int i=s.length(),j=p.length();
//都为空则为true
ss[0][0]=true;
//当s中不为空,p为空,一定匹配失败,false
for(int x=1;x<=i;x++){
ss[x][0]=false;
}
//s为空,满足a*c*的也可以为空,为空的取值为true
for(int y=1;y<=j;y++){
if(p[y-1]=='*')
ss[0][y]=ss[0][y-2];
else ss[0][y]=false;
}
for(int x=1;x<=i;x++)
for(int y=1;y<=j;y++){
//a*b,cb, b相等,比较a*与c是否相等
//a*b, c. b与'.' 等同,比较a*与c是否相等
if(p[y-1]=='.'||p[y-1]==s[x-1]){
ss[x][y]=ss[x-1][y-1];
}else{
if(p[y-1]=='*'){
//a,c*a*,只针对x,前者新来一个a,组成aa时,a==p[j-2],则看以前的内容a,c*a*,ss[x-1][y]
//bc,acd,只针对y,后者新来一个*,组成acd*时,如果两者最后一个字符不相等,则能看acd是否匹配
//比较c与c,c与cd任意一个满足即可满足条件
if(p[y-2]==s[x-1]||p[y-2]=='.'){
//若相等的话,如baa,ba*,通过ss[x][y]=ss[x-1][y],将baa转化至b,
//再通过ss[x][y]=ss[x][y-2],将ba*转化为b与b进行比较
ss[x][y]=ss[x-1][y]||ss[x][y-2];
}else{
//bc,acd,后者新来一个*,组成acd*时,如果两者最后一个字符不相等,则只能看bc与ac是否匹配ss[x][y-2]
ss[x][y]=ss[x][y-2];
}
}else{
// 针对x,y 来者不匹配 a!=p[j-2],ss[x][y]=false;
ss[x][y]=false;
}
}
}
return ss[i][j];
}
};