返回
Leetcode - 通配符匹配:算法和策略
闲谈
2023-11-05 04:27:21
- 问题
在 Leetcode 上,通配符匹配问题被表述为:给定一个字符串 s 和一个模式 p,其中 p 可能包含通配符 '.' 和 '','.' 可以匹配任何单个字符,'' 可以匹配任意数量的字符(包括 0 个)。请判断 s 是否与 p 匹配。
2. 算法策略
2.1 动态规划
动态规划是一种解决最优子结构问题的常用方法,对于通配符匹配问题,我们可以使用动态规划来求解。具体步骤如下:
- 创建一个二维表 dp,其中 dp[i][j] 表示字符串 s 的前 i 个字符是否与模式 p 的前 j 个字符匹配。
- 初始化 dp 表:
- dp[0][0] = true,因为空字符串与空模式总是匹配。
- 对于所有 j > 0,dp[0][j] = false,因为空字符串不能匹配非空模式。
- 对于所有 i > 0,dp[i][0] = false,因为非空字符串不能匹配空模式。
- 对于所有 i > 0 和 j > 0,根据以下规则计算 dp[i][j]:
- 如果 s[i] = p[j] 或 p[j] = '.',则 dp[i][j] = dp[i-1][j-1]。
- 如果 p[j] = '*',则有两种可能:
- dp[i][j] = dp[i-1][j],表示 '*' 匹配 0 个字符。
- dp[i][j] = dp[i][j-1],表示 '*' 匹配 1 个或多个字符。
2.2 贪婪算法
贪婪算法是一种在每一步做出看似最好的选择,从而达到全局最优解的算法。对于通配符匹配问题,我们可以使用贪婪算法来求解。具体步骤如下:
- 从字符串 s 和模式 p 的开头开始匹配。
- 如果 s[i] = p[j] 或 p[j] = '.',则匹配成功,i++ 和 j++。
- 如果 p[j] = '*',则有两种可能:
- 如果 s[i] = p[j-1],则匹配成功,i++ 和 j++。
- 否则,j++,继续尝试匹配。
- 重复步骤 2 和 3,直到到达字符串 s 和模式 p 的末尾。
3. 示例代码
def is_match(s, p):
"""
判断字符串 s 是否与模式 p 匹配。
Args:
s: 字符串 s
p: 模式 p
Returns:
bool: True if s matches p, False otherwise.
"""
# 创建 dp 表
dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
# 初始化 dp 表
dp[0][0] = True
for j in range(1, len(p) + 1):
dp[0][j] = False
for i in range(1, len(s) + 1):
dp[i][0] = False
# 计算 dp 表
for i in range(1, len(s) + 1):
for j in range(1, len(p) + 1):
if s[i-1] == p[j-1] or p[j-1] == '.':
dp[i][j] = dp[i-1][j-1]
elif p[j-1] == '*':
dp[i][j] = dp[i-1][j] or dp[i][j-1]
# 返回结果
return dp[len(s)][len(p)]
def is_match_greedy(s, p):
"""
使用贪婪算法判断字符串 s 是否与模式 p 匹配。
Args:
s: 字符串 s
p: 模式 p
Returns:
bool: True if s matches p, False otherwise.
"""
i = 0
j = 0
while i < len(s) and j < len(p):
if s[i] == p[j] or p[j] == '.':
i += 1
j += 1
elif p[j] == '*':
while j < len(p) and p[j] == '*':
j += 1
if j == len(p):
return True
i += 1
else:
return False
# 如果到达了字符串 s 和模式 p 的末尾,则匹配成功
return i == len(s) and j == len(p)
4. 总结
通配符匹配问题是 Leetcode 上一道经典的算法题,本文介绍了两种解决该问题的算法:动态规划和贪婪算法。通过这篇文章,您应该对如何解决通配符匹配问题有了一个更深入的理解。