Leetcode44通配符匹配
-
- [题解1 枚举情况(数学思维)](#题解1 枚举情况(数学思维))
- [题解2 DP](#题解2 DP)
给你一个输入字符串 (s) 和一个字符模式 § ,请你实现一个支持 '?' 和 '*' 匹配规则的通配符匹配:
- '?' 可以匹配任何单个字符
- '*' 可以匹配任意字符序列(包括空字符序列)
- 判定匹配成功的充要条件是:字符模式必须能够完全匹配输入字符串(而不是部分匹配)
cpp
示例 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
仅由小写英文字母、'?'
或'*'
组成
题解1 枚举情况(数学思维)
cpp
class Solution {
public:
bool isMatch(string s, string p) {
/*
注意:在自写代码的第一版里,未考虑到p短s回溯位置不确定的情况
Key: startIdx和matchIdx
*/
int i=0, j=0, startIdx=-1, matchIdx=-1;
const int m = s.size(), n = p.size();
while(i < m){
if(j < n && (s[i]==p[j] || '?'==p[j])){
i ++;
j ++;
}else if(j < n && '*' == p[j]){
startIdx = j;
matchIdx = i;
// '*'匹配空字符
j ++;
}else if(startIdx != -1){
// '*'不匹配空字符, s[matchIdx]被'*'替掉
j = startIdx+1;
i = ++matchIdx;
}else return false;
}
// 检查p末尾是否可以匹配'*'
while(j < n && '*' == p[j]) j++;
return j == n;
}
};
题解2 DP
cpp
class Solution {
public:
bool isMatch(string s, string p) {
const int m = s.size();
const int n = p.size();
// dp下标代表长度,所以需要多申请1b
vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
dp[0][0] = 1;
// 先检查边界(转移函数会用)
for(int i=1; i <= n; i++){
if('*' == p[i-1]) dp[0][i] = 1;
// 出现了非*就不满足了
else break;
}
// dp转移(双循环模板)
for(int i=1; i <= m; i++){
for(int j=1; j <=n; j++){
if('*' == p[j-1]) dp[i][j] = dp[i-1][j] || dp[i][j-1];
else if('?' == p[j-1] || s[i-1] == p[j-1]) dp[i][j] = dp[i-1][j-1];
}
}
return dp[m][n];
}
};