Regular Expression Matching(正则表达式匹配)
题目大意:输入字符串 (s) 和模式串 §, 实现正则表达式匹配, 支持 ‘.’ and ‘*’。
‘.’ 匹配任意单个字符
‘*’ 匹配0个或多个与前一个字符相同的字符。
注意:必须是全部匹配才算匹配,部分匹配不算
Note:
s可以为空且只含小写字符a-z.
p可以为空且只含小写字符a-z 和字符 . 或 *
样例输入:
s = “ab”
p = “.*”
输出: true
解释: “.*” 意味着0个或多个任意字符.
代码思路:
1.最好的情况:不含 * 号,则从头匹配到尾即可
2.含 * 的情况:
2.1 匹配0个与*号前一个字符相同的字符(即删除这两个字符)后能否匹配成功。
2.2 若当前字符相等,匹配+1个 与*号前一个字符(即当前字符)相同的字符后能否匹配成功。
//递归实现
var isMatch = function(s, p) {
let sLen=s.length,pLen=p.length;
if(pLen==0){ return sLen==pLen;} //如果模式串为空
let first=(sLen!=0 && (s[0]==p[0] || p[0]=='.')); //两个字符串都不为空,且首字符相等
if(pLen>=2 && p[1]=='*'){ //模式串长度>2 且第二个字符为*
//去除前两个字符后能匹配上 或者 将*变成前面字符后能匹配上
return (isMatch(s,p.substring(2)) || (first && isMatch(s.substring(1),p)));
}else{ //模式串长度为1
return first && isMatch(s.substring(1),p.substring(1)); //匹配下一个字符
}
};
/**
* @param {string} s
* @param {string} p
* @return {boolean}
*/
//DP实现,基于上面的递归,但是比纯递归快很多
var DP;
var dp = function(i,j,s, p) {
let sLen=s.length,pLen=p.length;
if(DP[i][j]!=undefined){ return DP[i][j]==true;} //如果有一个字符串为空
let ans;
if(j==p.length){ ans=(i==sLen);}
else {
let first=(i<sLen && (s[i]==p[j] || p[j]=='.'));
if((j+1)<pLen && p[j+1]=='*'){
ans=(dp(i,j+2,s,p) || (first && dp(i+1,j,s,p)));
}else{
ans=first && dp(i+1,j+1,s,p);
}
}
DP[i][j]=ans ? true : false;
return ans;
};
function isMatch(s,p){
DP=new Array(s.length+1);
for(let i=0;i<=s.length;i++){
DP[i]=new Array(p.length+1);
}
return dp(0,0,s,p);
}