https://leetcode.cn/problems/regular-expression-matching/desc...
三、动态规划版本
class Solution8 {
public boolean isMatch(String str, String pat) {
boolean match[][] = new boolean[str.length() + 1][pat.length() + 1];
// init for s.length = 0;
match[0][0] = true;
// si和pi都作为substring的第二个参数的含义,其实际用到charAt得为i-1,i起点为1,终点为length+1
for (int pi = 1; pi < pat.length() + 1; pi++) {
boolean nextIsStar = pi < pat.length() && pat.charAt(pi) == '*';
if (nextIsStar) {
match[0][pi] = match[0][pi - 1];
pi++;
match[0][pi] = match[0][pi - 1];
} else {
break;
}
}
for (int si = 1; si < str.length() + 1; si++) {
for (int pi = 1; pi < pat.length() + 1; pi++) {
char c = pat.charAt(pi - 1);
boolean nextIsStar = pi < pat.length() && pat.charAt(pi) == '*';
if (!nextIsStar) { // a-z
match[si][pi] = match[si - 1][pi - 1] && (c == str.charAt(si - 1) || c == '.'); // 因为pat没走完,可能被后面的 a*匹配到
} else if (c == '.') { //.*
for (int k = si; k >= 0; k--) {
if (match[k][pi - 1]) {
match[si][pi] = true;
break;
}
}
} else { // a-z*
if (match[si][pi - 1]) {
match[si][pi] = true;
} else {
for (int k = si; k >= 1; k--) {
if (str.charAt(k - 1) == c) { // 如果最后一位是a,循环直到 viSubStr.match(wholePat) || wholeStr.match(subPat)
if (match[k - 1][pi]) {
match[si][pi] = true;
break;
}
} else { // 否则,wholeStr.match(subPat)
match[si][pi] = match[k][pi - 1];
break;
}
}
}
}
if (nextIsStar) {
match[si][pi + 1] = match[si][pi];
pi++;
}
}
}
return match[str.length()][pat.length()];
}
}
二、递归+缓存版本
Cache中的map可替换为Boolean[][],初始化大小决定了其花费的时间
class Solution6 {
static char a = 'a';
static char z = 'z';
static char A = 'A';
static char Z = 'Z';
static char point = '.';
static char star = '*';
// 如何分类
// a* .* . abc
public boolean isMatch(String str, String pattern) {
Cache cache = Cache.init(str, pattern);
return cache.match();
}
static class Cache {
Integer si = 0;
Integer pi = 0;
private String string;
private String pattern;
private Map<Integer, Map<Integer, Boolean>> map;
public boolean match() {
return match(string.length(), pattern.length());
}
private boolean match(Integer se, Integer pe) {
// String str = string.substring(si, se);
// String pat = pattern.substring(pi, pe);
if (se <= si) {
return emptyMatch(pi, pe);
} else if (pe <= pi) {
return false;
}
Boolean res = hitCache(se, pe);
if (res != null) {
return res;
}
res = false;
char lastC = pattern.charAt(pe - 1);
if (lastC == star) { // .*
for (int j = se; j >= si; j--) {
if (match(j, pe - 1)) {
res = true;
break;
}
}
} else if (lastC >= A && lastC <= Z) { // a* - z*
for (int j = se - 1; j >= si; j--) {
if (string.charAt(j) == (char) (lastC + 32)) { // 如果最后一位是a
if (match(j, pe) || match(se, pe - 1)) { // 且 subStr.match(wholePat) || wholeStr.match(subPat)
res = true;
break;
}
} else {
res = match(se, pe - 1); // wholeStr.match(subPat)
break;
}
}
} else { // a-z || .
res = (lastC == point || string.charAt(se - 1) == lastC) && match(se - 1, pe - 1);
}
putCache(se, pe, res);
return res;
}
public Boolean hitCache(Integer se, Integer pe) {
if (map.containsKey(se)) {
return map.get(se).get(pe);
} else {
map.put(se, new HashMap<>());
return null;
}
}
public void putCache(Integer se, Integer pe, Boolean result) {
map.get(se).put(pe, result);
}
private boolean emptyMatch(Integer pi, Integer pe) {
for (int i = pi; i < pe; i++) {
char c = pattern.charAt(i);
if (c >= a && c <= z || c == point) {
return false;
}
}
return true;
}
public static Cache init(String str, String pattern) {
Cache cache = new Cache();
cache.string = str;
cache.pattern = formatPat(pattern);
cache.map = new HashMap<>();
return cache;
}
//*, A-Z, a-z, .
private static String formatPat(String pattern) {
List<Character> parts = new ArrayList<>();
for (int i = 0; i < pattern.length(); i++) {
if (i + 1 < pattern.length() && pattern.charAt(i + 1) == star) {
if (pattern.charAt(i) == point) { // .*
parts.add(star);
} else { // a* - z*
parts.add((char) (pattern.charAt(i) - 32));
}
i++;
} else { // a-z .
parts.add(pattern.charAt(i));
}
}
return parts.stream()
.map(String::valueOf)
.collect(Collectors.joining());
}
}
}
一、递归版本
class Solution3 {
char a = 'a';
char z = 'z';
char A = 'A';
char Z = 'Z';
char point = '.';
char star = '*';
public boolean isMatch(String str, String pattern) {
String newPattern = formatPat(pattern);
return match(str, newPattern);
}
public boolean match(String str, String pat) {
if (str.length() == 0) {
return emptyMatch(pat);
}
if (pat.length() == 0) {
return false;
}
char lastC = pat.charAt(pat.length() - 1);
if (lastC == star) { // .*
for (int j = str.length(); j >= 0; j--) {
if (match(sub(str, j), lessOne(pat))) {
return true;
}
}
return false;
} else if (lastC >= A && lastC <= Z) { // a* - z*
for (int j = str.length() - 1; j >= 0; j--) {
if (str.charAt(j) == (char) (lastC + 32)) {
if (match(sub(str, j), pat) || match(str, lessOne(pat))) {
return true;
}
} else {
return match(str, lessOne(pat));
}
}
return false;
} else { // a-z || .
return (lastC == point || str.charAt(str.length() - 1) == lastC) && match(lessOne(str), lessOne(pat));
}
}
private boolean emptyMatch(String pat) {
for (int i = 0; i < pat.length(); i++) {
char c = pat.charAt(i);
if (c >= a && c <= z || c == point) {
return false;
}
}
return true;
}
private String sub(String str, int endIdx) {
if (endIdx <= 0) {
return "";
}
return str.substring(0, endIdx);
}
private String lessOne(String str) {
return sub(str, str.length() - 1);
}
//*, A-Z, a-z, .
private String formatPat(String pattern) {
List<Character> parts = new ArrayList<>();
for (int i = 0; i < pattern.length(); i++) {
if (i + 1 < pattern.length() && pattern.charAt(i + 1) == star) {
if (pattern.charAt(i) == point) { // .*
parts.add(star);
} else { // a* - z*
parts.add((char) (pattern.charAt(i) - 32));
}
i++;
} else { // a-z .
parts.add(pattern.charAt(i));
}
}
StringBuilder sb = new StringBuilder();
for (Character part : parts) {
sb.append(part);
}
return sb.toString();
}
}
零、测试用例
public static void main(String[] args) {
print("aab", "c*a*b", true);
print("aa", "a", false);
print("aa", "a*", true);
print("ab", ".*", true);
print("mississippi", "mis*is*ip*.", true);
print("mississippi", "mis*is*p*.", false);
print("aaa", "ab*a*c*a", true);
print("a", ".*..a*", false);
print("aab", "b.*", false);
print("a", "..*", true);
print("acbbcbcbcbaaaca", "ac*.a*ac*.*a", false);
}
private static void print(String str, String pattern, Boolean expectRes) {
log.info("str {} pattern {} match {}, expect {}", str, pattern, new Solution8().isMatch(str, pattern), expectRes);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。