问题
实现正则表达式匹配,支持“.”和“*”。
‘.’:匹配任何单个字符。
‘*’:匹配0个或多个前面的元素。
一些例子:
isMatch(“aa”,“a”) return false
isMatch(“aa”,“aa”) return true
isMatch(“aaa”,“aa”) return false
isMatch(“aa”, “a*”) return true
isMatch(“aa”, “.*”) return true
isMatch(“ab”, “.*”) return true
isMatch(“aab”, “c*a*b”) return true
解法
1. 分析
首先,这是最困难的问题之一。很多情况都很难处理。
问题应简化为处理2种基本情况:
-
pattern的第二个字符是"*":
这种情况,如果pattern的第一个字符不是".",pattern和string的第一个字符应该相同。然后继续匹配剩余部分。
-
pattern的第二个字符不是"*":
如果pattern的第一个字符是"."或者pattern的第一个字符== string的第一个字符,则继续匹配剩余的字符。
2. 解法一(简短)
public static boolean isMatch(String s, String p) {
if (p.length() == 0) {
return s.length() == 0;
}
// 模板p的只有1个字符或第二个字符不是*
if (p.length() == 1 || p.charAt(1) != '*') {
// s为空字符串 或 (模板p不是"."且模板p和s的第一个字符不相同)
if (s.length() < 1 || (p.charAt(0) != '.' && s.charAt(0) != p.charAt(0))) {
return false;
}
// 第一个字符匹配成功,往下匹配
return isMatch(s.substring(1), p.substring(1));
} else {
// else包含的情况:模板p的长度>1,且第二个字符是*
int len = s.length();
int i = -1;
while (i < len && (i < 0 || p.charAt(0) == '.' || p.charAt(0) == s.charAt(i))) {
if (isMatch(s.substring(i + 1), p.substring(2))) {
return true;
}
i++;
}
return false;
}
}
3. 解法二(阅读性更好)
public static boolean isMatch2(String s, String p) {
if (p.length() == 0) {
return s.length() == 0;
}
// 特殊情况 p长度为1
if (p.length() == 1) {
if (s.length() < 1) {
return false;
} else if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != '.')) {
return false;
} else {
return isMatch(s.substring(1), p.substring(1));
}
}
if (p.charAt(1) != '*') {
// 第二个字符数是*
if (s.length() < 1) {
return false;
}
if ((p.charAt(0) != s.charAt(0)) && (p.charAt(0) != '.')) {
return false;
} else {
return isMatch(s.substring(1), p.substring(1));
}
} else {
// 第二个字符不是*
if (isMatch(s, p.substring(2))) {
return true;
}
int i = 0;
while (i < s.length() && (s.charAt(i) == p.charAt(0) || p.charAt(0) == '.')) {
if (isMatch(s.substring(i + 1), p.substring(2))) {
return true;
}
i++;
}
return false;
}
}