题目简介:
给定一个字符串 (s
) 和一个字符模式 (p
) ,实现一个支持 '?'
和 '*'
的通配符匹配。
1 2
| '?' 可以匹配任何单个字符。 '*' 可以匹配任意字符串(包括空字符串)。
|
两个字符串完全匹配才算匹配成功。
说明:
s
可能为空,且只包含从 a-z
的小写字母。
p
可能为空,且只包含从 a-z
的小写字母,以及字符 ?
和 *
示例 1:
1 2 3 4 5
| 输入: s = "aa" p = "a" 输出: false 解释: "a" 无法匹配 "aa" 整个字符串。
|
示例 2:
1 2 3 4 5
| 输入: s = "aa" p = "*" 输出: true 解释: '*' 可以匹配任意字符串。
|
示例 3:
1 2 3 4 5
| 输入: s = "cb" p = "?a" 输出: false 解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
|
示例 4:
1 2 3 4 5
| 输入: s = "adceb" p = "*a*b" 输出: true 解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".
|
示例 5:
1 2 3 4
| 输入: s = "acdcb" p = "a*c?b" 输出: false
|
思路:
这题与10.正则表达式匹配挺像的,不过考虑的方面没那题这么多。
利用动态规划的思想,dp[i][j]
代表两字符串以s[i]
与p[j]
为结尾的匹配情况。
首先是特殊情况的判断:
- s为空,p为空,返回
true
。
- s不为空,p为空,返回
false
。
p[i]
在匹配时有以下三种情况:
p[j] == s[i]
,此时dp[i][j] == dp[i - 1][j - 1]
。
p[j] == ?
,此时p[j]
可以匹配任意单个字符,所以dp[i][j] == dp[i - 1][j - 1]
。
p[j] == *
,此时p[j]
可以匹配0, 1,多次字符。所以dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 1][j];
tip:
- 为方便处理边界问题,s,p最前面都加一个空格。
- 首先初始化
dp[0][j]
,即s为空,p不为空的情况。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class Solution { public: bool isMatch(string s, string p) {
if(s.empty() && p.empty()) return true; if(p.empty() && !s.empty()) return false;
s = " " + s; p = " " + p;
vector<vector<bool>> dp(s.length(), vector<bool>(p.length(), false));
dp[0][0] = true;
for(int j = 1; j < p.length(); j++){
if(p[j] == '*') dp[0][j] = true; else break; }
for(int i = 1; i < s.length(); i++){
for(int j = 1; j < p.length(); j++){
if(s[i] == p[j] || p[j] == '?') dp[i][j] = dp[i - 1][j - 1]; else if(p[j] == '*'){
dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 1][j]; } } } return dp[s.length() - 1][p.length() - 1]; } };
|