通配符匹配(Wildcard Matching)的进阶版:支持多模式匹配的通配符匹配
字数 1783 2025-11-29 14:15:07
通配符匹配(Wildcard Matching)的进阶版:支持多模式匹配的通配符匹配
题目描述
给定一个输入字符串 s 和一组模式 patterns,每个模式可以包含普通字符、通配符 ?(匹配任意单个字符)和 *(匹配任意字符序列,包括空序列)。判断字符串 s 是否能被 patterns 中的任意一个模式完全匹配。注意:匹配必须是完整的,即整个字符串 s 需被某个模式完全覆盖。
示例
输入:s = "abcd", patterns = ["a*c?", "b*d", "a?d"]
输出:true
解释:模式 "a*c?" 可以匹配 "abcd"(a 匹配 a,* 匹配 bc,c? 匹配 cd)。
解题过程
此问题可转化为对每个模式单独判断是否匹配 s,只要有一个模式匹配成功即返回 true。核心是扩展经典的通配符匹配动态规划解法,以支持多模式。
步骤1:定义DP状态
对于单个模式 p,定义 dp[i][j] 表示字符串 s 的前 i 个字符和模式 p 的前 j 个字符是否匹配。
i范围:0到len(s)(i=0表示空字符串)j范围:0到len(p)(j=0表示空模式)
步骤2:初始化边界条件
dp[0][0] = true:空字符串匹配空模式。- 对于
j ≥ 1,仅当p的前j个字符全是*时,dp[0][j] = true(因为*可匹配空序列)。 - 对于
i ≥ 1,dp[i][0] = false:空模式无法匹配非空字符串。
步骤3:状态转移方程
遍历 i 从 1 到 len(s),j 从 1 到 len(p):
- 若
p[j-1]是普通字符:需满足s[i-1] == p[j-1]且dp[i-1][j-1] == true。- 即:
dp[i][j] = dp[i-1][j-1] && (s[i-1] == p[j-1])
- 即:
- 若
p[j-1]是?:它匹配任意单个字符,直接继承dp[i-1][j-1]。- 即:
dp[i][j] = dp[i-1][j-1]
- 即:
- 若
p[j-1]是*:可匹配空序列(忽略*,即dp[i][j-1])或匹配多个字符(保留*继续匹配,即dp[i-1][j])。- 即:
dp[i][j] = dp[i][j-1] || dp[i-1][j]
- 即:
步骤4:多模式处理
对 patterns 中的每个模式 p,执行上述DP过程,若任意 p 满足 dp[len(s)][len(p)] == true,则返回 true;否则检查下一个模式。若所有模式均不匹配,返回 false。
步骤5:优化
- 当某个模式匹配成功时立即返回,避免不必要的计算。
- 可提前检查模式是否包含普通字符(非通配符)且其数量超过
s的长度,直接跳过。
举例说明
以 s = "abcd", p = "a*c?" 为例:
- 初始化:
dp[0][0] = true,dp[0][1](p[0]='a')为false,dp[0][2](p[1]='*')需看前一位:dp[0][1]为false,但dp[0][2]需结合*的规则,实际因*可匹配空,需从头检查:正确初始化后dp[0][2] = true(因为a*中*前有a,但初始化时i=0仅当模式前j个全为*才真,此处需按规则重新计算)。
具体计算时:i=1,j=1:s[0]='a'匹配p[0]='a',且dp[0][0]=true→dp[1][1]=true。i=1,j=2:p[1]='*',可忽略(继承dp[1][1]=true)或匹配多字符(但i=1时dp[0][2]未计算,需逐行计算)。
最终dp[4][4]为true,匹配成功。
通过以上步骤,可高效解决多模式通配符匹配问题。