leetcode刷题日记 -- 44通配符匹配(动态规划 + c++思路详解)
·
# 1. 题目
给你一个输入字符串 (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 仅由小写英文字母、'?' 或 '*' 组成
2. 题目分析
- 该题是10.正则表达式匹配的变型
- 也是使用动态规划方程来解决的经典题型
3. 思路分析
3.1 定义状态
使用二维数组表示状态:
dp[i][j]
图示:

举例
s = "aaaa"
p = "aa?*"
bp[2][2] : 表示sub_s("aa")和sub_p("aa")是否匹配
3.2 状态转移方程dp[i][j] = ?
- 当
p[j-1] == 小写字母- 当sub_s和sub_p的最后一个字母相同的时候
dp[i][j] = dp[i-1][j-1]; - 当sub_s和sub_p的最后一个字母相同的时候
dp[i][j] =false;
- 当sub_s和sub_p的最后一个字母相同的时候
- 当
p[j-1] == '?'dp[i][j] = dp[i-1][j-1];
- 当
p[j-1] == '*'- 当’*'匹配0个字符的时候
dp[i][j] = dp[i][j-1]; - 当’*'匹配0个字符的时候
dp[i][j] = dp[i-1][j-1]; - 当’*'匹配0个字符的时候
dp[i][j] = dp[i-2][j-1]; - …
对于3,等价于 dp[i][j] = dp[i][j-1] || dp[i-1][j-1] || dp[i-1][j-1] || ...;
重要的变型:(数学方法)
上述等式令i= i-1,可得:dp[i-1][j] = dp[i-1][j-1] || dp[i-1][j-1] || dp[i-2][j-1]...;
将两式共同部分消除可得:dp[i][j] = dp[i][j-1] || dp[i-1][j];
- 当’*'匹配0个字符的时候
3.3 边界条件(初始化条件)
根据状态转移方程i,j都是从小到大递增的,因此需要明确三个边界条件:
dp[0][0]
dp[i][0]
dp[0][j]
dp[0][0] = true;dp[i][0] = false; ( i > 0)- 分情况:
- 当
p[j] == '*'时,dp[0][j] = dp[0][j-1]; j > 0 -
- 当
p[j] == '*'时,dp[0][j] = false;
- 当
- 当
4. 解题代码
4.1 初始化:
class Solution {
public:
bool isMatch(string s, string p) {
// 状态转移方程
int size_s = s.size();
int size_p = p.size();
std::vector<std::vector<bool>> bp(size_s + 1, std::vector<bool>(size_p + 1, false));
bp[0][0] = true;
for (int idx = 1; idx < size_p + 1; ++idx) {
bp[0][idx] = (p[idx - 1] == '*') && (bp[0][idx - 1]);
}
...
}
};
4.2 循环求解动态转移数组
class Solution {
public:
bool isMatch(string s, string p) {
...
for (int i = 1; i < size_s + 1; ++i) {
for (int j = 1; j < size_p + 1; ++j) {
if (p[j - 1] != '*') {
if (p[j - 1] == '?' || p[j - 1] == s[i - 1]) {
bp[i][j] = bp[i - 1][j - 1];
}
} else {
bp[i][j] = (bp[i][j - 1] || bp[i - 1][j]);
}
}
}
return bp[size_s][size_p];
}
};
注:虽然通过了,但是细节待完善,代码只做思路提示,欢迎评论区讨论。
更多推荐
所有评论(0)