10. 正则表达式匹配
FPG-Alan opened this issue · comments
Yang Yang commented
https://leetcode.cn/problems/regular-expression-matching/
动态规划
dp[i][j]
表示 p[0~j)
字串能否匹配s[0~i)
字串, 最终结果就是dp[s.length][p.length]
(注意, 这里采取左闭右开区间, 为了防止在j-2时数组越界)
状态转移公式需要根据p[j-1]的值分情况来看:
- 若
p[j-1]
是字母或'.', 则dp[i][j]
=>dp[i-1][j-1]
&& (s[i-1] === p[j-1] || p[j-1] === '.'
) - 若
p[j-1]
是'*':- 若p[j-2] === s[i-1]:
- 让'*'匹配零次,此时
dp[i][j]
=>dp[i][j-2]
- 让'*'匹配一次或多次,此时
dp[i][j]
=>dp[i-1][j]
- 让'*'匹配零次,此时
- 若
p[j-2]
!==s[i-1]
, 此时只能让'*'匹配零次dp[i][j]
=>dp[i][j-2]
- 若p[j-2] === s[i-1]:
var isMatch = function (s, p) {
const dp = new Array(s.length + 1);
for (let i = 0, l = dp.length; i < l; i += 1) {
dp[i] = new Array(p.length + 1).fill(false);
}
dp[0][0] = true;
for (let j = 1; j < p.length + 1; j++) {
if (p[j - 1] == "*") dp[0][j] = dp[0][j - 2];
}
for (let i = 1, l = dp.length; i < l; i += 1) {
for (let j = 1, k = dp[i].length; j < k; j += 1) {
if (p[j - 1] === "." || p[j - 1] === s[i - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else if (p[j - 1] === "*") {
if (p[j - 2] === s[i - 1] || p[j - 2] === ".") {
// 此时可以选择*匹配模式
// 若匹配0次, 直接扔掉, 那么i不变, j往前两位(扔掉*和前面匹配的那个字母)
// 若匹配1次, 则i往前一位, j不变, 在下一轮继续匹配
// 若匹配多次, 和匹配一次同理
dp[i][j] = dp[i][j - 2] || dp[i - 1][j];
} else if (p[j - 2] !== s[i - 1]) {
// *前一位不匹配, 此时若还想继续匹配, 只能将*视为匹配0次
dp[i][j] = dp[i][j - 2];
}
}
}
}
return dp[s.length][p.length];
};
console.log(isMatch("aab", "c*a*b"));