通配符匹配

08/18/2025

leetcode-通配符匹配

题目描述

给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 '?' 和 '*' 匹配规则的通配符匹配:
'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符序列(包括空字符序列)。
判定匹配成功的充要条件是:字符模式必须能够 完全匹配 输入字符串(而不是部分匹配)。
 
示例 1:
输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
 
示例 2:
输入:s = "aa", p = "*"
输出:true
解释:'*' 可以匹配任意字符串。
 
示例 3:
输入:s = "cb", p = "?a"
输出:false
解释:'?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
 
提示:
0 <= s.length, p.length <= 2000
s 仅由小写英文字母组成
p 仅由小写英文字母、'?' 或 '*' 组成

本人题解

超出时间限制,1710 / 1811 个通过的测试用例

/**
 * @param {string} s
 * @param {string} p
 * @return {boolean}
 */
var isMatch = function(s, p) {
  let is = 0, ip = 0;
  p = mergeMultiStar(p)
  while (is <= s.length && ip < p.length) {
    if (p[ip] === '*') {
      return recursion(s, p, is, ip + 1)
    } else if (p[ip] === '?') {
      if (is === s.length) {
        return false
      }
    } else {
      if (s[is] !== p[ip]) {
        return false;
      }
    }
    is++;
    ip++;
  }
  if (is < s.length || ip < p.length) {
    return false;
  }
  return true;
};
 
function mergeMultiStar(p) {
  return p.replace(/\*+/, '*')
}
 
function recursion(s, p, is, ip) {
  const subP = p.substr(ip, p.length)
  for (let i = is; i < s.length + 1; i++) {
    const subS = s.substr(i, s.length)
    if (isMatch(subS, subP)) {
      return true
    }
  }
  return false
}

分析

  1. 字符模式只有三种情况,? 和一般的字符,都只需要两个下标都后移即可,所以主要问题出现在*这里
  2. 当遇到*时,就会出现多种分岔,因为*可以匹配任意字符串。
  3. 在遇到*时,需要回溯递归,直到最后的结果出来。
  4. 当然,也可能会遇到特别多的*连在一起,这对性能影响很大,所以需要提前把*合并成一个*
  5. 最后,如果两个下标都走完了,说明匹配成功,否则匹配失败

当然,我目前的代码还是有瑕疵,超出时间限制。。。