正则表达式匹配
请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
每次从字符串中拿出一个字符和模式中的字符来匹配,相对而言,模式中的第二个字符不是 ’ * ’ 的时候,比较简单,直接进行比较即可。
如果第二个字符是 ’ * ‘,那么有三种情况,分别表示,’ * ’ 只匹配 一次、匹配 0 次、匹配多次
- 在模式上向后移动两位,在字符串上向后移动一位。这种情况表示,两者只匹配一次,
- 在模式上向后移动两位,在字符串不移动。这种情况表示,模式上的不匹配,即包含 0 次
- 在模式上不移动,在字符串上向后移动一位。这种情况表示,模式上匹配多次。
这里解释一下,在 matchCore 中,不进行 str.length == strCur && pattern.length != patCur 的判断。因为即使 strCur 到头了,pattern 后面也依然可以有字符。
贴一个比较好的分析
首先,考虑特殊情况:
- 两个字符串都为空,返回true
- 当第一个字符串不空,而第二个字符串空了,返回false(因为这样,就无法匹配成功了,而如果第一个字符串空了,第二个字符串非空,还是可能匹配成功的,比如第二个字符串是" a * a * a * a ", 由于 ’ * '之前的元素可以出现0次,所以有可能匹配成功)
- 之后就开始匹配第一个字符,这里有两种可能:匹配成功或匹配失败。但考虑到pattern下一个字符可能是’ * ‘, 这里我们分两种情况讨论:pattern下一个字符为’ * ‘或不为’ * ':
- pattern下一个字符不为’ * ‘:这种情况比较简单,直接匹配当前字符。如果匹配成功,继续匹配下一个;如果匹配失败,直接返回false。注意这里的“匹配成功”,除了两个字符相同的情况外,还有一种情况,就是pattern的 当前字符为’ . ‘,同时str的当前字符不为‘\0’
- pattern下一个字符为 ’ * '时,稍微复杂一些,因为 ’ * '可以代表0个或多个。这里把这些情况都考虑到:
- ’ * '匹配0个字符时,str当前字符不变,pattern当前字符后移两位,跳过这个 ’ * '符号;
- 当’ * '匹配1个,str当前字符移向下一个,pattern当前字符后移两位
- 当’ * '匹配多个时,str当前字符移向下一个,pattern当前字符不变。
public class Solution {
public boolean match(char[] str, char[] pattern){
if(str == null || pattern == null){
return false;
}
return matchCore(str, pattern, 0, 0);
}
public boolean matchCore(char[] str, char[] pattern, int strCur, int patCur){
% 判断两者是否都到了末尾,是的话,则匹配成功
if(str.length == strCur && pattern.length == patCur){
return true;
}
% 判断字符串没有到末尾,模式到末尾,则匹配失败
if(str.length != strCur && pattern.length == patCur){
return false;
}
% 如果模式的下一个字符是 ' * ' 且 没有超出界限
if(patCur + 1 < pattern.length && pattern[patCur + 1] == '*'){
% 判断模式的当前字符是否和字符串的字符匹配 或者 模式的字符是 ' . ' 这两种情况都算匹配成功
if((strCur != str.length && pattern[patCur] == str[strCur]) || (pattern[patCur] == '.' && str.length != strCur)){
% 3个或,第一个是匹配一次、第二个是匹配多次、第三个是匹配0次
return matchCore(str, pattern, strCur+1, patCur+2) ||
matchCore(str, pattern, strCur+1, patCur) ||
matchCore(str, pattern, strCur, patCur+2);
}else {
% 如果模式的当前字符和字符串的字符匹配失败。这种情况不是返回false,而是认为匹配0次
return matchCore(str, pattern, strCur, patCur+2);
}
}
% 如果模式的下一个字符不是' * ' ,则按照正常一一匹配
if((strCur != str.length && str[strCur] == pattern[patCur]) || (pattern[patCur] == '.' && str.length != strCur)){
return matchCore(str, pattern, strCur+1, patCur+1);
}
return false;
}
}
测试用例
功能测试:模式字符串李包含普通字符、 ’ * ’ 、’ . ’ 、模式字符串和输入字符串匹配、不匹配
特殊输入测试:输入字符串和模式字符串都为 null、空字符串;
本文深入解析了正则表达式匹配算法,详细阐述了如何处理包含‘.‘和‘*‘的正则表达式,通过递归方式实现字符串与模式的完全匹配,探讨了‘*‘符的三种匹配情况,提供了完整的Java代码实现及测试用例。
1914

被折叠的 条评论
为什么被折叠?



