modify code

master
algorithmzuo 1 year ago
parent a64b46ff5a
commit 6679ad61f7

@ -3,129 +3,105 @@ package class12;
// 测试链接 : https://leetcode.com/problems/regular-expression-matching/ // 测试链接 : https://leetcode.com/problems/regular-expression-matching/
public class Code04_RegularExpressionMatch { public class Code04_RegularExpressionMatch {
public static boolean isValid(char[] s, char[] e) { // 暴力递归
// s中不能有'.' or '*' public static boolean isMatch1(String str, String pat) {
for (int i = 0; i < s.length; i++) {
if (s[i] == '*' || s[i] == '.') {
return false;
}
}
// 开头的e[0]不能是'*',没有相邻的'*'
for (int i = 0; i < e.length; i++) {
if (e[i] == '*' && (i == 0 || e[i - 1] == '*')) {
return false;
}
}
return true;
}
// 初始尝试版本,不包含斜率优化
public static boolean isMatch1(String str, String exp) {
if (str == null || exp == null) {
return false;
}
char[] s = str.toCharArray(); char[] s = str.toCharArray();
char[] e = exp.toCharArray(); char[] p = pat.toCharArray();
return isValid(s, e) && process(s, e, 0, 0); return process1(s, p, 0, 0);
} }
// str[si.....] 能不能被 exp[ei.....]配出来! true false // s[i....]能不能被p[j....]完全匹配出来
public static boolean process(char[] s, char[] e, int si, int ei) { public static boolean process1(char[] s, char[] p, int i, int j) {
if (ei == e.length) { // exp 没了 str if (i == s.length) {
return si == s.length; // s没了
} if (j == p.length) {
// exp[ei]还有字符 // 如果p也没了返回true
// ei + 1位置的字符不是*
if (ei + 1 == e.length || e[ei + 1] != '*') {
// ei + 1 不是*
// str[si] 必须和 exp[ei] 能配上!
return si != s.length && (e[ei] == s[si] || e[ei] == '.') && process(s, e, si + 1, ei + 1);
}
// exp[ei]还有字符
// ei + 1位置的字符是*!
while (si != s.length && (e[ei] == s[si] || e[ei] == '.')) {
if (process(s, e, si, ei + 2)) {
return true; return true;
} else {
// 如果p[j+1]是*那么p[j..j+1]可以消掉然后看看p[j+2....]是不是都能消掉
return j + 1 < p.length && p[j + 1] == '*' && process1(s, p, i, j + 2);
} }
si++; } else if (j == p.length) {
// s有
// p没了
return false;
} else {
if (j + 1 == p.length || p[j + 1] != '*') {
// s[i....]
// p[j....]
// 如果p[j+1]不是*,那么当前的字符必须能匹配:(s[i] == p[j] || p[j] == '?')
// 同时后续也必须匹配上process1(s, p, i + 1, j + 1);
return (s[i] == p[j] || p[j] == '.') && process1(s, p, i + 1, j + 1);
} else {
// s[i....]
// p[j....]
// 如果p[j+1]是*
// 选择1: 当前p[j..j+1]是x*就是不让它搞定s[i],那么继续 : process1(s, p, i, j + 2)
boolean p1 = process1(s, p, i, j + 2);
// 选择2: 当前p[j..j+1]是x*如果可以搞定s[i],那么继续 : process1(s, p, i + 1, j)
// 如果可以搞定s[i] : (s[i] == p[j] || p[j] == '.')
// 继续匹配 : process1(s, p, i + 1, j)
boolean p2 = (s[i] == p[j] || p[j] == '.') && process1(s, p, i + 1, j);
// 两个选择有一个可以搞定就返回true都无法搞定返回false
return p1 || p2;
} }
return process(s, e, si, ei + 2);
} }
// 改记忆化搜索+斜率优化
public static boolean isMatch2(String str, String exp) {
if (str == null || exp == null) {
return false;
} }
// 记忆化搜索
public static boolean isMatch2(String str, String pat) {
char[] s = str.toCharArray(); char[] s = str.toCharArray();
char[] e = exp.toCharArray(); char[] p = pat.toCharArray();
if (!isValid(s, e)) { int n = s.length;
return false; int m = p.length;
} // dp[i][j] == 0表示没算过
int[][] dp = new int[s.length + 1][e.length + 1]; // dp[i][j] == 1表示没算过答案是true
// dp[i][j] = 0, 没算过! // dp[i][j] == 2表示没算过答案是false
// dp[i][j] = -1 算过返回值是false int[][] dp = new int[n + 1][m + 1];
// dp[i][j] = 1 算过返回值是true return process2(s, p, 0, 0, dp);
return isValid(s, e) && process2(s, e, 0, 0, dp);
} }
public static boolean process2(char[] s, char[] e, int si, int ei, int[][] dp) { public static boolean process2(char[] s, char[] p, int i, int j, int[][] dp) {
if (dp[si][ei] != 0) { if (dp[i][j] != 0) {
return dp[si][ei] == 1; return dp[i][j] == 1;
}
boolean ans;
if (i == s.length) {
if (j == p.length) {
ans = true;
} else {
ans = j + 1 < p.length && p[j + 1] == '*' && process2(s, p, i, j + 2, dp);
} }
boolean ans = false; } else if (j == p.length) {
if (ei == e.length) { ans = false;
ans = si == s.length;
} else { } else {
if (ei + 1 == e.length || e[ei + 1] != '*') { if (j + 1 == p.length || p[j + 1] != '*') {
ans = si != s.length && (e[ei] == s[si] || e[ei] == '.') && process2(s, e, si + 1, ei + 1, dp); ans = (s[i] == p[j] || p[j] == '.') && process2(s, p, i + 1, j + 1, dp);
} else { } else {
if (si == s.length) { // ei ei+1 * ans = process2(s, p, i, j + 2, dp) || ((s[i] == p[j] || p[j] == '.') && process2(s, p, i + 1, j, dp));
ans = process2(s, e, si, ei + 2, dp);
} else { // si没结束
if (s[si] != e[ei] && e[ei] != '.') {
ans = process2(s, e, si, ei + 2, dp);
} else { // s[si] 可以和 e[ei]配上
ans = process2(s, e, si, ei + 2, dp) || process2(s, e, si + 1, ei, dp);
}
} }
} }
} dp[i][j] = ans ? 1 : 2;
dp[si][ei] = ans ? 1 : -1;
return ans; return ans;
} }
// 动态规划版本 + 斜率优化 // 动态规划
public static boolean isMatch3(String str, String pattern) { public static boolean isMatch3(String str, String pat) {
if (str == null || pattern == null) {
return false;
}
char[] s = str.toCharArray(); char[] s = str.toCharArray();
char[] p = pattern.toCharArray(); char[] p = pat.toCharArray();
if (!isValid(s, p)) { int n = s.length;
return false; int m = p.length;
} boolean[][] dp = new boolean[n + 1][m + 1];
int N = s.length; dp[n][m] = true;
int M = p.length; for (int j = m - 2; j >= 0; j--) {
boolean[][] dp = new boolean[N + 1][M + 1]; dp[n][j] = p[j + 1] == '*' && dp[n][j + 2];
dp[N][M] = true; }
for (int j = M - 1; j >= 0; j--) { for (int i = n - 1; i >= 0; i--) {
dp[N][j] = (j + 1 < M && p[j + 1] == '*') && dp[N][j + 2]; for (int j = m - 1; j >= 0; j--) {
} if (j + 1 == p.length || p[j + 1] != '*') {
// dp[0..N-2][M-1]都等于false只有dp[N-1][M-1]需要讨论 dp[i][j] = (s[i] == p[j] || p[j] == '.') && dp[i + 1][j + 1];
if (N > 0 && M > 0) {
dp[N - 1][M - 1] = (s[N - 1] == p[M - 1] || p[M - 1] == '.');
}
for (int i = N - 1; i >= 0; i--) {
for (int j = M - 2; j >= 0; j--) {
if (p[j + 1] != '*') {
dp[i][j] = ((s[i] == p[j]) || (p[j] == '.')) && dp[i + 1][j + 1];
} else {
if ((s[i] == p[j] || p[j] == '.') && dp[i + 1][j]) {
dp[i][j] = true;
} else { } else {
dp[i][j] = dp[i][j + 2]; dp[i][j] = dp[i][j + 2] || ((s[i] == p[j] || p[j] == '.') && dp[i + 1][j]);
}
} }
} }
} }

Loading…
Cancel
Save