题目在这里。
简单翻译一下。就是实现这样一个正则表达式,支持'*'和'.'。
'*'不能单独出现,它之前必须有一个字符可以是a-z或者'.'。
'*'表示重复它之前的字母n次(n>=0)
'.'表示可以充当a-z的任意一个字符。
举几个例子:
1、
Input:
s = "aa"
p = "a"
Output: false
解释: "a" 不能完全匹配 "aa".
2、
Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*'重复a一次,这样变成aa,能和s匹配.
3、
Input:
s = "ab"
p = ".*"
Output: true
Explanation: "*" 重复'.'一次,变为..,..可匹配ab".
4、
Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c重复0次,a重复1次,变为aab,可以和s匹配。
下面讲下实现思路。
举例子说明吧:
假设s = "misissippppi",p="a*b*mis*sis*ip*i",s的指针称为i,p的指针称为j。
s[0] = 'm',p[0] = 'a',p[1] = '*',m和a不能匹配,并且p[1] = '*',这时候要跳过'a*'这个字符串向前匹配,也就是i=0,j = j+2(j=2)。
s[0] = 'm',p[2] = 'b',p[3] = '*' m和b不能匹配,并且p[3] = '*',这时候要跳过'b*'这个字符串向前匹配,也就是i=0,j = j+2(j=4)。
s[0] = 'm',p[4] = 'm',并且p[5] != '*',能匹配成功,i=i+1(i=1),j=j+1(j=5),继续匹配
... ...
s[2] = 's',p[6] = 's',并且p[7] == '*',因为此时不能确定's'要重复多少次,所以要测试,我们先假设重复0次,看s2和p[8]能不能匹配,如果能匹配,说明重复0次成功,如果不能匹配,i++,继续匹配。如果指针越界都没匹配成功,说明匹配失败,直接返回false。
完整的代码如下:
function myMatch(s,p,i,j){
if(j >= p.length){ //如果p的指针已经移出结尾,看s的指针,如果s的指针也移出结尾,返回匹配成功,否则匹配失败
return i >= s.length;
}
if(j == p.length-1){ //如果p的指针指向最后一位,那直接和s的最后一位比较即可,而且这里的的最后一位不可能是*号,因为如果是*,下面的代码会把*跳过
return (i == s.length -1) && (p.charAt(j) == s.charAt(i) || p.charAt(j) == '.')
}
if(j+1 < p.length && p[j+1] != '*'){//如果j+1不是*
if(p[j] == s[i] || p[j] == '.'){ //并且和s能匹配上
return myMatch(s,p,i+1,j+1); //看下一位能不能匹配上
}
return false;
}
with(j < p.length && i < s.length && (p[j] == s[i]) || p[j] == '.'){ //如果j+1是*,并且能匹配成功
if(myMatch(s,p,i,j+2)){ //假设*号重复它前面的字符0,1,2,3,4...次,测试成功一次即可
return true;
}
i++;
}
return myMatch(s,p,i,j+2); //如果j+1是*,并且不能匹配成功,跳过这个x*这两个字符
}
var ss = "mississippppi";
var pp = "a*b*mis*is*ip*i";
console.log(myMatch(ss,pp,ss.length-1,pp.length-1));
这里需要注意的是这段代码的一个边界问题:
if(myMatch(s,p,i,j+2)){ //假设*号重复它前面的字符0,1,2,3,4...次,测试成功一次即可
return true;
}
举个例子:
s = abc;
p= a*abc;
因为s[0]和p[0]匹配成功,p[1]是'*',所以如果认为s[0]和p[0]是匹配成功的,那么接下来结果肯定是匹配失败,因为这里s[0]要和p[2]匹配才能保证最终结果匹配成功。