给你一个输入字符串(s)和一个字符模式(p),请你实现一个支持'?'和'*'匹配规则的通配符匹配:
'?'可以匹配任何单个字符。'*'可以匹配任意字符序列(包括空字符序列)。
判定匹配成功的充要条件是:字符模式必须能够完全匹配输入字符串(而不是部分匹配)。
示例:
输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。
/**
* @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)