今天在刷剑指offer的时候,遇到一个正则表达式匹配的问题,看题解时觉得题解有点问题,所以就自己写个博客记录一下。
题目描述
请实现一个函数用来匹配包含"*“和”.“的正则表达式。模式中的字符‘.’表示任意一个字符,而”*"表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
题解
由于".“可以与任意字符匹配,因此匹配时遇到”.“很容易解决。但是对于”*“字符,就得分情况讨论了:一种是字符串中的字符与模式串中”*“之前的字符不匹配,这种情况下我们可以忽略”*“字符和该字符之前的那个字符,即在模式串上向后移动两位,如"aa"和"ac*a"是匹配的;另一种情况是字符串中的字符与模式串中”*“之前的那个字符匹配,这种情况下又可细分为三种情况:一种是字符串中的字符向后移动一位,模式串不移动,如"aaaac"与"aa*c"是匹配的;另一种字符串的字符移动一位,而模式串中的字符移动两个字符,如"aac"与"aa*c"是匹配的。还有一种是忽略”*"和该字符之前的字符,即字符串中的字符不移动,模式串中的字符移动两位,如"aac"与"aa*ac"也是匹配的。
代码
public class Solution {
public boolean match(char[] str, char[] pattern)
{
return matchStr(str,0,pattern,0);
}
public boolean matchStr(char[] str,int i,char[] pattern,int j){
//两者都为空
if(i==str.length&&j==pattern.length){
return true;
}
//模式串为空
else if(j==pattern.length){
return false;
}
boolean next=(j+1<pattern.length&&pattern[j+1]=='*');
//下一个字符为*时
if(next){
//'\*'之前的字符匹配时,上文中提到的三种情况
if(i<str.length&&(pattern[j]=='.'||str[i]==pattern[j])){
return matchStr(str,i,pattern,j+2)||matchStr(str,i+1,pattern,j)||matchStr(str,i+1,pattern,j+2);
}
//字符不匹配,忽略'\*'及其之前的字符
return matchStr(str,i,pattern,j+2);
}
}
else {
//下一个字符不是'\*',就是正常的字符串匹配,如果当前字符匹配,就开始匹配下一个字符,否则就匹配失败
if(i<str.length&&(pattern[j]=='.'||str[i]==pattern[j])){
return matchStr(str,i+1,pattern,j+1);
}
else{
return false;
}
}
}
}