Java算法题-解析 "通配符匹配" 算法问题
题目:
给定一个字符串 s 和一个包含通配符 ?
和 *
的模式串 p,请实现一个函数来判断 s 是否匹配 p。
?
可以匹配任何单个字符。*
可以匹配任意字符串(包括空字符串)。
引言:
"通配符匹配" 是一个关于字符串匹配和模式匹配的算法题。解决这个问题需要对字符串和模式的匹配规则有深刻理解,同时需要找到一种方法来处理通配符的匹配。通过解答这个问题,我们可以提升对字符串匹配、模式匹配和问题规模的考虑,同时也能拓展对字符串操作和匹配规则的应用。
算法思路:
我们可以使用动态规划的方法来解决这个问题。具体思路如下:
- 创建一个布尔类型的二维数组
dp
,其中dp[i][j]
表示字符串s
的前i
个字符和模式p
的前j
个字符是否匹配。 - 初始化
dp[0][0] = true
,表示两个空字符串是匹配的。 - 处理模式中的通配符
*
,在模式中遇到*
时,可以将其匹配为空字符串,所以dp[0][j]
(模式中前j
个字符匹配空字符串)的状态与dp[0][j-1]
相关。 遍历字符串和模式,对于每个位置
(i, j)
:- 如果
s[i-1]
和p[j-1]
相等,或者p[j-1]
是通配符?
,则dp[i][j] = dp[i-1][j-1]
。 - 如果
p[j-1]
是通配符*
,则dp[i][j] = dp[i][j-1]
(匹配空字符串)或dp[i-1][j]
(匹配任意字符串)。
- 如果
- 返回
dp[m][n]
,其中m
和n
分别为字符串s
和模式p
的长度。
代码实现:
以下是使用 Java 实现的 "通配符匹配" 算法的示例代码:
public class WildcardMatching {
public boolean isMatch(String s, String p) {
int m = s.length();
int n = p.length();
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;
for (int j = 1; j <= n; j++) {
if (p.charAt(j - 1) == '*') {
dp[0][j] = dp[0][j - 1];
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') {
dp[i][j] = dp[i - 1][j - 1];
} else if (p.charAt(j - 1) == '*') {
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
}
}
}
return dp[m][n];
}
}
算法分析:
- 时间复杂度:动态规划的时间复杂度为 O(m * n),其中
m
和n
分别为字符串s
和模式p
的长度。 - 空间复杂度:动态规划需要创建一个二维数组
dp
,所以空间复杂度为 O(m * n)。
示例和测试:
假设给定的字符串为 s = "adceb"
和模式为 p = "*a*b"
,根据算法,字符串和模式匹配,返回 true
。
我们可以使用以下代码进行测试:
public class Main {
public static void main(String[] args) {
WildcardMatching solution = new WildcardMatching();
String s = "adceb";
String p = "*a*b";
boolean result = solution.isMatch(s, p);
System.out.println("Is matching: " + result);
}
}
总结:
"通配符匹配" 算法问题要求判断字符串和模式是否匹配,其中模式包含通配符 ?
和 *
,是一个考察字符串匹配和模式匹配的问题。通过实现这个算法,我们可以提升对字符串匹配、模式匹配和问题规模的考虑,同时也能拓展对动态规划的应用。这个问题强调了如何使用动态规划来处理字符串匹配问题,通过建立状态转移方程和处理边界情况,来得出最终的匹配结果。