Keshawn_lu's Blog

Leetcode 44. 通配符匹配

字数统计: 673阅读时长: 3 min
2020/07/05 Share

题目简介:

给定一个字符串 (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]在匹配时有以下三种情况:

  1. p[j] == s[i],此时dp[i][j] == dp[i - 1][j - 1]
  2. p[j] == ?,此时p[j]可以匹配任意单个字符,所以dp[i][j] == dp[i - 1][j - 1]
  3. 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] == '*'){

//匹配0, 1, 多次字符
dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 1][j];
}
}
}

return dp[s.length() - 1][p.length() - 1];
}
};
CATALOG
  1. 1. 题目简介:
  2. 2. 思路:
  3. 3. 代码如下: