leetcode44 通配符匹配
描述
给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
思路-动态规划
- 对规则进行处理,比如多个*进行合并等
- 逐条进行匹配
- 所有规则匹配完后,如果通过返回true
- 如果规则是字符串,直接匹配固定长度字符串
- 如果是rule【number,boolean】
- 如果rule[1]=true,匹配固定长度字符
- 如果rule[1]=false,说明有*,可以递归匹配
- 并通过动态规划,记录规则,对应那些字符串位置不能匹配成功
效率
代码如下
function isMatch(s: string, p: string): boolean {
const dp = [];
const rules = getRules(p);
return volidStr(s, rules, 0, 0);
function getRules(p: string) {
const rules = [];
let i = 0,
j = 0;
while (i < p.length) {
const preChar = p.charAt(i);
j = i + 1;
if (preChar !== "*" && preChar !== "?") {
while (j < p.length) {
const nextChar = p.charAt(j);
if (nextChar !== "*" && nextChar !== "?") {
j++;
} else {
break;
}
}
rules.push(p.substring(i, j));
i = j;
} else {
const temp: [number, boolean?] = preChar === "*" ? [0] : [1, true];
while (j < p.length) {
const nextChar = p.charAt(j);
if (nextChar !== "*" && nextChar !== "?") {
break;
}
if (nextChar === "*" && temp[1]) {
temp[1] = false;
} else if (nextChar === "?") {
temp[0] = temp[0] + 1;
}
j++;
}
rules.push(temp);
i = j;
}
}
return rules;
}
function volidStr(str: string, rules, i: number, j: number): boolean {
if (
i === rules.length &&
(j === str.length ||
(j < str.length && Array.isArray(rules[i - 1]) && !rules[i - 1][1]))
) {
return true;
} else if (i === rules.length) {
return false;
} else {
const rule = rules[i];
//通配符之类的
if (Array.isArray(rule)) {
return volidStr(str, rules, i + 1, j + rule[0]);
} else {
const preRule = rules[i - 1];
if (Array.isArray(preRule) && !preRule[1]) {
let index = str.indexOf(rule, j);
while (index >= 0) {
if (!dp[i + 1]) {
dp[i + 1] = [];
}
dp[i + 1][rule.length + index] =
dp[i + 1][rule.length + index] === undefined
? volidStr(str, rules, i + 1, rule.length + index)
: dp[i + 1][rule.length + index];
if (!dp[i + 1][rule.length + index]) {
index = str.indexOf(rule, index + 1);
} else {
return true;
}
}
return false;
} else {
if (str.substring(j, rule.length + j) === rule) {
return volidStr(str, rules, i + 1, rule.length + j);
} else {
return false;
}
}
}
}
}
}
const cases: [string, string][] = [
["ab", "*a"],
["", "?"],
["aa", "a"],
["bbbab", "*??a?"],
["abcabczzzde", "*abc???de*"],
[
"abbabaaabbabbaababbabbbbbabbbabbbabaaaaababababbbabababaabbababaabbbbbbaaaabababbbaabbbbaabbbbababababbaabbaababaabbbababababbbbaaabbbbbabaaaabbababbbbaababaabbababbbbbababbbabaaaaaaaabbbbbaabaaababaaaabb",
"**aa*****ba*a*bb**aa*ab****a*aaaaaa***a*aaaa**bbabb*b*b**aaaaaaaaa*a********ba*bbb***a*ba*bb*bb**a*b*bb",
],
];
const res = [false, false, false, true, true, false];
cases.forEach((item: [string, string], index) =>
console.log(res[index] === isMatch(item[0], item[1]))
);