返回

Leetcode - 通配符匹配:算法和策略

闲谈

  1. 问题

在 Leetcode 上,通配符匹配问题被表述为:给定一个字符串 s 和一个模式 p,其中 p 可能包含通配符 '.' 和 '','.' 可以匹配任何单个字符,'' 可以匹配任意数量的字符(包括 0 个)。请判断 s 是否与 p 匹配。

2. 算法策略

2.1 动态规划

动态规划是一种解决最优子结构问题的常用方法,对于通配符匹配问题,我们可以使用动态规划来求解。具体步骤如下:

  1. 创建一个二维表 dp,其中 dp[i][j] 表示字符串 s 的前 i 个字符是否与模式 p 的前 j 个字符匹配。
  2. 初始化 dp 表:
    • dp[0][0] = true,因为空字符串与空模式总是匹配。
    • 对于所有 j > 0,dp[0][j] = false,因为空字符串不能匹配非空模式。
    • 对于所有 i > 0,dp[i][0] = false,因为非空字符串不能匹配空模式。
  3. 对于所有 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 贪婪算法

贪婪算法是一种在每一步做出看似最好的选择,从而达到全局最优解的算法。对于通配符匹配问题,我们可以使用贪婪算法来求解。具体步骤如下:

  1. 从字符串 s 和模式 p 的开头开始匹配。
  2. 如果 s[i] = p[j] 或 p[j] = '.',则匹配成功,i++ 和 j++。
  3. 如果 p[j] = '*',则有两种可能:
    • 如果 s[i] = p[j-1],则匹配成功,i++ 和 j++。
    • 否则,j++,继续尝试匹配。
  4. 重复步骤 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 上一道经典的算法题,本文介绍了两种解决该问题的算法:动态规划和贪婪算法。通过这篇文章,您应该对如何解决通配符匹配问题有了一个更深入的理解。