返回轨道
算法 · 2026-05-14 · 22 阅读

P173 通配符匹配

算法 22 阅读

信号摘要

难度:Hard · 时长:18:11 · leetcode 44 · lintcode 192

P173 通配符匹配

未对外公开播放权限
点击查看说明

描述

这个题目说的是,给你一个字符串 s,和一个模式串 p。你要实现一个能支持 ? 和 * 的通配符匹配。其中,? 可以匹配任意单个非空字符,* 可以匹配 0 个字符或任意多个字符。

s 可以是空字符串,也可以是只包含小写字母的非空字符串;p 可以是空字符串,也可以是只包含小写字母、? 或 * 的非空字符串。

注意,p 一定是合法的模式串,并且只有 p 匹配 s 的整个字符串时,才返回 true。

比如说,

s: aa p: a

模式串 p 不包含通配符,且 s 和 p 不相同,于是这一组 p 和 s 不匹配。

再比如说,

s: ac p: *

  • 可以匹配任意多个字符,因此这一组 p 和 s 匹配,返回 true。

如果这一组的 s 不变,仍然为 ac,但是把 p 改成 *d:

s: ac p: *d

由于 p 中的字符 d 无法在 s 中找到匹配字符,因此这一组 p 和 s 不匹配,返回 false。

最后再举个例子:

s: abcde p: ad?

我们只需要让第一个 * 匹配空字符,第二个 * 匹配 bc,最后的 ? 匹配字符 e,就可以把模式串变成 abcde。于是对于这一组字符串,p 可以匹配 s。

相关视频:简易正则表达式匹配

代码

public class AlgoCasts {

  private boolean isEqual(char sc, char pc) {
    return sc == pc || pc == '?';
  }

  // Time: O(m*n), Space: O(m*n)
  public boolean isMatchDP(String s, String p) {
    if (s == null || p == null) return false;
    int m = s.length(), n = p.length();
    boolean[][] d = new boolean[m+1][n+1];
    d[0][0] = true;
    for (int i = 1; i <= m; ++i)
      d[i][0] = false;
    for (int j = 1; j <= n; ++j) {
      if (p.charAt(j-1) == '*') d[0][j] = d[0][j-1];
      else d[0][j] = false;
    }

    for (int i = 1; i <= m; ++i) {
      for (int j = 1; j <= n; ++j) {
        char sc = s.charAt(i-1), pc = p.charAt(j-1);
        if (isEqual(sc, pc)) d[i][j] = d[i-1][j-1];
        else if (pc == '*') d[i][j] = d[i][j-1] || d[i-1][j];
        else d[i][j] = false;
      }
    }
    return d[m][n];
  }

  // Time: O(m*n), Space: O(1)
  public boolean isMatchGreedy(String s, String p) {
    if (s == null || p == null) return false;
    int m = s.length(), n = p.length();
    int i = 0, j = 0, sBegin = -1, pBegin = -1;
    while (i < m) {
      if (j < n && isEqual(s.charAt(i), p.charAt(j))) {
        ++i; ++j;
      } else if (j < n && p.charAt(j) == '*') {
        ++j;
        sBegin = i;
        pBegin = j;
      } else if (pBegin != -1) {
        ++sBegin;
        i = sBegin;
        j = pBegin;
      } else return false;
    }
    while (j < n && p.charAt(j) == '*') ++j;
    return j == n;
  }

}

📡 通讯频道