|
|
package class12;
|
|
|
|
|
|
// 测试链接 : https://leetcode.com/problems/regular-expression-matching/
|
|
|
public class Code04_RegularExpressionMatch {
|
|
|
|
|
|
// 暴力递归
|
|
|
public static boolean isMatch1(String str, String pat) {
|
|
|
char[] s = str.toCharArray();
|
|
|
char[] p = pat.toCharArray();
|
|
|
return process1(s, p, 0, 0);
|
|
|
}
|
|
|
|
|
|
// s[i....]能不能被p[j....]完全匹配出来
|
|
|
public static boolean process1(char[] s, char[] p, int i, int j) {
|
|
|
if (i == s.length) {
|
|
|
// s没了
|
|
|
if (j == p.length) {
|
|
|
// 如果p也没了,返回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);
|
|
|
}
|
|
|
} 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;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 记忆化搜索
|
|
|
public static boolean isMatch2(String str, String pat) {
|
|
|
char[] s = str.toCharArray();
|
|
|
char[] p = pat.toCharArray();
|
|
|
int n = s.length;
|
|
|
int m = p.length;
|
|
|
// dp[i][j] == 0,表示没算过
|
|
|
// dp[i][j] == 1,表示没算过答案是true
|
|
|
// dp[i][j] == 2,表示没算过答案是false
|
|
|
int[][] dp = new int[n + 1][m + 1];
|
|
|
return process2(s, p, 0, 0, dp);
|
|
|
}
|
|
|
|
|
|
public static boolean process2(char[] s, char[] p, int i, int j, int[][] dp) {
|
|
|
if (dp[i][j] != 0) {
|
|
|
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);
|
|
|
}
|
|
|
} else if (j == p.length) {
|
|
|
ans = false;
|
|
|
} else {
|
|
|
if (j + 1 == p.length || p[j + 1] != '*') {
|
|
|
ans = (s[i] == p[j] || p[j] == '.') && process2(s, p, i + 1, j + 1, dp);
|
|
|
} else {
|
|
|
ans = process2(s, p, i, j + 2, dp) || ((s[i] == p[j] || p[j] == '.') && process2(s, p, i + 1, j, dp));
|
|
|
}
|
|
|
}
|
|
|
dp[i][j] = ans ? 1 : 2;
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
// 动态规划
|
|
|
public static boolean isMatch3(String str, String pat) {
|
|
|
char[] s = str.toCharArray();
|
|
|
char[] p = pat.toCharArray();
|
|
|
int n = s.length;
|
|
|
int m = p.length;
|
|
|
boolean[][] dp = new boolean[n + 1][m + 1];
|
|
|
dp[n][m] = true;
|
|
|
for (int j = m - 2; j >= 0; j--) {
|
|
|
dp[n][j] = p[j + 1] == '*' && dp[n][j + 2];
|
|
|
}
|
|
|
for (int i = n - 1; i >= 0; i--) {
|
|
|
for (int j = m - 1; j >= 0; j--) {
|
|
|
if (j + 1 == p.length || p[j + 1] != '*') {
|
|
|
dp[i][j] = (s[i] == p[j] || p[j] == '.') && dp[i + 1][j + 1];
|
|
|
} else {
|
|
|
dp[i][j] = dp[i][j + 2] || ((s[i] == p[j] || p[j] == '.') && dp[i + 1][j]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return dp[0][0];
|
|
|
}
|
|
|
|
|
|
}
|