题目:请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配。
方法:有两个指针s和p,s指向字符串,p指向模式
1.首先我们分析出现'.'的情况,从题目中可以知道,这个符号可以代表任意一个字符,也就是这两个指针同时后移一位(或者是这两个字符相等)
2.当出现'*'的时候:
(1)当s和p相等(注意这个相等),p+1是‘*’的时候,会出现三种情况:
a.模式不变(也就是指针p不变),s向后移动一位。比如abbcd和ab*cf,其中s和p都指向了b。由于b出现了多次,应该不着急移动p,所以此时s+1即可。
b.忽略这个‘*’,p向后移动两位,s向后移动一位。比如abcd和ab*cf,其中s和p都指向了b。此时应该s+1和p+2
c.忽略这个'*’,p向后移动两位,s不变。比如"cba","cb*a*a",我也可以认为,p指向的第1个a没出现过,即使你相等。因此此时可以s不动,p+2(也就是直接跳到最后比较)。
(2)当s和p不相等的时候,p+1是‘*’的情况,相当于这个没出现,p向后移动两位。
由于把真正的相等和'.'标记的相等并成一类,就只用考虑'*'。如果不出现星号,就常规比较,常规比较肯定出现相等或者不等两类。如果出现星号,就考虑两个指针指的是否相等,不等,则p指针直接+2。两个指针相等,则有3种情况并列处理。再在这些判断中,加入对应边界条件,就可以很容易理解并写出代码了。
public class Solution {
public boolean match(char[] str, char[] pattern)
{
if(str==null || pattern==null){
return false;
}
return match(str,0,pattern,0);
}
public boolean match(char[] str,int s,char[] pattern,int p){
if(s==str.length && p==pattern.length){
return true;
}
if(s<str.length && p==pattern.length){
return false;
}
//下一个指针指向的是*
if(p+1<pattern.length && pattern[p+1]=='*'){
//出现了*号,并且s和p指的相同
if((s<str.length && pattern[p]=='.') || (s<str.length && str[s]==pattern[p] )){
return match(str,s,pattern,p+2)
|| match(str,s+1,pattern,p+2)
|| match(str,s+1,pattern,p);
}
else{
return match(str,s,pattern,p+2);
}
}
//下一个不是*
if(s<str.length&& (str[s]==pattern[p] || pattern[p]=='.')){
return match(str,s+1,pattern,p+1);
}
return false;
}
}