模糊搜索验证
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 48 ms, 内存: 15 MB
/*
* 思路:
* 虽然 Java Stream 并不直接适用于这种动态规划问题,但我们可以使用 Stream 来简化一些数据处理的步骤。
* 因此,解决方案还是基于动态规划,只是部分操作可以使用 Stream 来完成。
*/
import java.util.stream.IntStream;
public class RegexMatchingStream {
public boolean isMatch(String article, String input) {
int m = article.length();
int n = input.length();
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;
IntStream.range(1, n + 1).forEach(j -> {
if (input.charAt(j - 1) == '*') {
dp[0][j] = dp[0][j - 2];
}
});
IntStream.range(1, m + 1).forEach(i -> {
IntStream.range(1, n + 1).forEach(j -> {
if (input.charAt(j - 1) == '.' || input.charAt(j - 1) == article.charAt(i - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else if (input.charAt(j - 1) == '*') {
dp[i][j] = dp[i][j - 2];
if (input.charAt(j - 2) == '.' || input.charAt(j - 2) == article.charAt(i - 1)) {
dp[i][j] = dp[i][j] || dp[i - 1][j];
}
}
});
});
return dp[m][n];
}
}
解释
方法:
此题解采用了动态规划(DP)的方法来解决正则表达式匹配问题。解决方案通过递归函数 dp(i, j) 检查原始字符串 s 从位置 i 开始的子串是否可以被模式 p 从位置 j 开始的子串匹配。使用 memoization 技术(memo 字典)来避免重复计算相同参数的函数调用,从而提高效率。对于基本情况,当模式 p 已经全部匹配完毕 (j == n),检查 s 是否也完全匹配 (i == m)。若 p 未结束但 s 已结束,则检查剩余的 p 是否可以匹配空字符串。递归地处理模式中的特殊字符 '*' 和 '.',其中 '.' 可以匹配任意单个字符,'*' 表示前一个字符可以出现零次或多次。
时间复杂度:
O(m*n)
空间复杂度:
O(m*n)
代码细节讲解
🦆
动态规划算法中,你是如何确定初始条件以及状态转移方程的?
▷🦆
在处理字符'*'时,`dp(i, j+2)` 和 `dp(i+1, j)` 分别代表什么含义,为什么需要两种处理方式?
▷🦆
递归函数中,当原文字符串 `s` 已经结束但模式字符串 `p` 未结束时,为什么要检查 `(n - j) % 2 == 1` 这个条件?
▷🦆
为什么在模式字符串 `p` 中连续的'*'字符后面要紧接着检查 `while j + 1 < n and p[j+1] == '*'`,这个循环的目的是什么?
▷