给你一个字符串 s
和一个字符规律 p
,请你来实现一个支持 '.'
和 '*'
的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s
的,而不是部分字符串。
说明:
s
可能为空,且只包含从a-z
的小写字母。p
可能为空,且只包含从a-z
的小写字母,以及字符.
和*
。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
示例 3:
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
class Solution {
public static void main(String[] args) {
boolean inMountainArray = new Solution().isMatch("mississippi", "mis*is*p*.");
System.out.println(inMountainArray);
}
public boolean isMatch(String s, String p) {
if (s == null || p == null) {
return false;
}
if (s.equals(p)) {
return true;
}
if ("".equals(s)) {
return isMatchEmpty(p);
}
for (int i = 0; i < s.length(); i++) {
if (i >= p.length()) {
return false;
}
if (!isEqual(s.charAt(i), p.charAt(i))) {
if (p.charAt(i) == '*') {
//当前是*
if (p.charAt(i - 1) == '.') {
//前一个是. 需要p的后续和s的末尾匹配
String pstr = p.substring(i + 1);
if (isMatchEmpty(pstr)) {
return true;
}
//遍历s的尾部,找到匹配就返回true
for (int j = i - 1; j < s.length() + 1; j++) {
String substring = s.substring(j);
if (isMatch(substring, pstr)) {
return true;
}
}
} else {
//不是.*通配符
if (isMatch(s.substring(i - 1), p.substring(i + 1))) {
//消除前一个后匹配
return true;
}
if (isMatch(s.substring(i), p.substring(i + 1))) {
//去除*后匹配
return true;
}
//重复N次匹配
if (s.charAt(i) == p.charAt(i - 1)) {
String value = String.valueOf(s.charAt(i));
String sStr = s.substring(i + 1);
String pStr = p.substring(i + 1);
//s和p去除N次重复
while (sStr.startsWith(value)) {
sStr = sStr.substring(1);
}
while (pStr.startsWith(value) || pStr.startsWith("*")) {
pStr = pStr.substring(1);
}
//是否匹配
if (isMatch(sStr, pStr)) {
return true;
} else {
//去除p中匹配value的符号,是否匹配
String format;
while (!(format = removeStartWords(pStr, value)).equals(pStr)) {
if (isMatch(sStr, format)) {
return true;
}
pStr = format;
}
}
}
}
} else if (i + 2 < p.length() && p.charAt(i + 1) == '*') {
//后一个是* 消除后匹配
return isMatch(s.substring(i), p.substring(i + 2));
}
return false;
}
}
//p超出长度
if (isMatchEmpty(p.substring(s.length()))) {
//后续为空
return true;
}
//p末尾和s最后一个字符匹配
return isMatchAWord(s.charAt(s.length() - 1), p.substring(s.length() - 1));
}
/**
* p是否为Empty
*/
public boolean isMatchEmpty(String p) {
if (p == null) {
return false;
}
if ("".equals(p)) {
return true;
}
if (p.charAt(p.length() - 1) != '*') {
return false;
}
String[] split = p.split("\\*");
for (String str : split) {
if (str.length() > 1) {
return false;
}
}
return true;
}
/**
* p是否匹配char
*/
public boolean isMatchAWord(char s, String p) {
if (p == null || p.length() == 0) {
return false;
}
if (!p.endsWith(String.valueOf(s)) && !p.endsWith("*") && !p.endsWith(".")) {
return false;
}
List<String> collect1 = Arrays.stream(p.split("\\*")).filter(str -> str.length() > 2).collect(Collectors.toList());
if (!collect1.isEmpty()) {
return false;
}
List<String> collect2 = Arrays.stream(p.split("\\*")).filter(str -> str.length() == 2).collect(Collectors.toList());
if (collect2.size() > 1) {
return false;
} else if (collect2.size() == 1) {
return collect2.get(0).startsWith(String.valueOf(s)) && p.endsWith("*");
}
List<String> collect = Arrays.stream(p.split("\\*")).filter(str -> str.length() == 1 && isEqual(s, str.charAt(0))).collect(Collectors.toList());
return !collect.isEmpty();
}
/**
* 去除连续重复word
*/
public String removeStartWords(String s, String word) {
if (1 < s.length() && s.charAt(1) == '*') {
return s.substring(2);
} else if (s.startsWith(word) || s.startsWith(".")) {
return s.substring(1);
}
return s;
}
/**
* char是否匹配
*/
public boolean isEqual(char s, char p) {
return s == p || p == '.';
}
}