LeetCode(44): 通配符匹配

时间:2022-10-12 09:43:13

Hard!

题目描述:

给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。

'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。

两个字符串完全匹配才算匹配成功。

说明:

  • s 可能为空,且只包含从 a-z 的小写字母。
  • p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:
s = "aa"
p = "*"
输出: true
解释: '*' 可以匹配任意字符串。

示例 3:

输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。

示例 4:

输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".

示例 5:

输入:
s = "acdcb"
p = "a*c?b"
输入: false

解题思路:

这道题通配符匹配问题还是小有难度的,这道里用了贪婪算法Greedy Alogrithm来解,由于有特殊字符*和?,其中?能代替任何字符,*能代替任何字符串,那么我们需要定义几个额外的指针,其中scur和pcur分别指向当前遍历到的字符,再定义pstar指向p中最后一个*的位置,sstar指向此时对应的s的位置,具体算法如下:

- 定义scur, pcur, sstar, pstar

- 如果*scur存在

- 如果*scur等于*pcur或者*pcur为 '?',则scur和pcur都自增1

- 如果*pcur为'*',则pstar指向pcur位置,pcur自增1,且sstar指向scur

- 如果pstar存在,则pcur指向pstar的下一个位置,scur指向sstar自增1后的位置

- 如果pcur为'*',则pcur自增1

- 若*pcur存在,返回False,若不存在,返回True

C语言解法一:

 bool isMatch(char *s, char *p) {
char *scur = s, *pcur = p, *sstar = NULL, *pstar = NULL;
while (*scur) {
if (*scur == *pcur || *pcur == '?') {
++scur;
++pcur;
} else if (*pcur == '*') {
pstar = pcur++;
sstar = scur;
} else if (pstar) {
pcur = pstar + ;
scur = ++sstar;
} else return false;
}
while (*pcur == '*') ++pcur;
return !*pcur;
}

这道题也能用动态规划Dynamic Programming来解,写法跟之前那道题Regular Expression Matching很像,但是还是不一样。外卡匹配和正则匹配最大的区别就是在星号的使用规则上,对于正则匹配来说,星号不能单独存在,前面必须要有一个字符,而星号存在的意义就是表明前面这个字符的个数可以是任意个,包括0个,那么就是说即使前面这个字符并没有在s中出现过也无所谓,只要后面的能匹配上就可以了。而外卡匹配就不是这样的,外卡匹配中的星号跟前面的字符没有半毛钱关系,如果前面的字符没有匹配上,那么直接返回false了,根本不用管星号。而星号存在的作用是可以表示任意的字符串,当然只是当匹配字符串缺少一些字符的时候起作用,当匹配字符串包含目标字符串没有的字符时,将无法成功匹配。

C++解法一:

 class Solution {
public:
bool isMatch(string s, string p) {
int m = s.size(), n = p.size();
vector<vector<bool>> dp(m + , vector<bool>(n + , false));
dp[][] = true;
for (int i = ; i <= n; ++i) {
if (p[i - ] == '*') dp[][i] = dp[][i - ];
}
for (int i = ; i <= m; ++i) {
for (int j = ; j <= n; ++j) {
if (p[j - ] == '*') {
dp[i][j] = dp[i - ][j] || dp[i][j - ];
} else {
dp[i][j] = (s[i - ] == p[j - ] || p[j - ] == '?') && dp[i - ][j - ];
}
}
}
return dp[m][n];
}
};