【JS每日一算法】38.通配符匹配(动态规划)

292 阅读3分钟

给你一个输入字符串(s)和一个字符模式(p),请你实现一个支持'?''*'匹配规则的通配符匹配:

  • '?'可以匹配任何单个字符。
  • '*'可以匹配任意字符序列(包括空字符序列)。

判定匹配成功的充要条件是:字符模式必须能够完全匹配输入字符串(而不是部分匹配)。

  示例:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

更多JS版本题解点击链接关注该仓库👀

/**
 * @description: 动态规划   TC:O(n^2)  SC:O(n^2)
 * @author: JunLiangWang
 * @param {*} s  原串
 * @param {*} p  匹配字符串
 * @return {*}
 */
function dp(s,p)
{
    /**
     * 该方案使用动态规划的方式,构造一个[p.length+1,s.length+1]的二维矩阵,
     * 行从1开始对应匹配字符串字符索引,列从1开始对应原串字符索引,之所以行
     * 列都加了1个长度,是因为0行/0列可代表匹配字符串/原串为空的情况, 也
     * 方便后续处理,该矩阵[i,j]的状态代表:匹配字符从0到i-1处能否与原串字
     * 符从0到j-1匹配,匹配成功为1,失败为0。如果矩阵最后一个状态为1,则证明
     * 匹配字符串与原串匹配成功。
     */

    // 如果原串等于匹配字符串,直接返回true
    if(s===p)return true;
    // 定义dp矩阵(行从1开始对应匹配字符串字符索引,列从1开始对应原串字符索引)
    // 之所以行列都加了1个长度,是因为0行/0列可代表匹配字符串/原串为空的情况,
    // 也方便后续处理
    let dpArray=new Array(p.length+1).fill(0).map(()=>new Array(s.length+1).fill(0));
    // 当两者都为空字符串时,此时两字符匹配,因此初始化[0][0]位置为1
    dpArray[0][0]=1;
    // 遍历匹配字符串每个字符
    for(let i=1;i<=p.length;i++)
    {
        // 当匹配字符为"*"时,由于"*"可匹配零个字符,因此其
        // ([i][0])位置状态应为上一匹配字符0列([i-1][0])位置状态
        if(p[i-1]==="*")dpArray[i][0]=dpArray[i-1][0];
        // 遍历原串每个字符
        for(let j=1;j<=s.length;j++)
        {
            // 如果当前匹配字符等于"*",当"*"匹配0个字符时,其状态应等于上一个匹配字符
            // 匹配原串当前字符的状态即dpArray[i-1][j],当"*"匹配n个字符时,其状态应
            // 等于当前匹配字符匹配原串上一字符的状态即dpArray[i][j-1],因此此处状态
            // 为两者或的结果
            if(p[i-1]==="*")dpArray[i][j]=dpArray[i-1][j]||dpArray[i][j-1];
            // 当前匹配字符匹配原串成功,当前状态则等于上一个匹配字符/原串字符匹配的情况
            else if(p[i-1]==="?"||p[i-1]===s[j-1])dpArray[i][j]=dpArray[i-1][j-1];
        }
    }
    // 如果最后一个字符匹配成功,则证明匹配字符串能匹配原串
    return dpArray[p.length][s.length]==1;
}

来源:力扣(LeetCode)