LeetCode(44): 通配符匹配
Posted Ariel_一只猫的旅行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode(44): 通配符匹配相关的知识,希望对你有一定的参考价值。
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语言解法一:
1 bool isMatch(char *s, char *p) { 2 char *scur = s, *pcur = p, *sstar = NULL, *pstar = NULL; 3 while (*scur) { 4 if (*scur == *pcur || *pcur == \'?\') { 5 ++scur; 6 ++pcur; 7 } else if (*pcur == \'*\') { 8 pstar = pcur++; 9 sstar = scur; 10 } else if (pstar) { 11 pcur = pstar + 1; 12 scur = ++sstar; 13 } else return false; 14 } 15 while (*pcur == \'*\') ++pcur; 16 return !*pcur; 17 }
这道题也能用动态规划Dynamic Programming来解,写法跟之前那道题Regular Expression Matching很像,但是还是不一样。外卡匹配和正则匹配最大的区别就是在星号的使用规则上,对于正则匹配来说,星号不能单独存在,前面必须要有一个字符,而星号存在的意义就是表明前面这个字符的个数可以是任意个,包括0个,那么就是说即使前面这个字符并没有在s中出现过也无所谓,只要后面的能匹配上就可以了。而外卡匹配就不是这样的,外卡匹配中的星号跟前面的字符没有半毛钱关系,如果前面的字符没有匹配上,那么直接返回false了,根本不用管星号。而星号存在的作用是可以表示任意的字符串,当然只是当匹配字符串缺少一些字符的时候起作用,当匹配字符串包含目标字符串没有的字符时,将无法成功匹配。
C++解法一:
1 class Solution { 2 public: 3 bool isMatch(string s, string p) { 4 int m = s.size(), n = p.size(); 5 vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false)); 6 dp[0][0] = true; 7 for (int i = 1; i <= n; ++i) { 8 if (p[i - 1] == \'*\') dp[0][i] = dp[0][i - 1]; 9 } 10 for (int i = 1; i <= m; ++i) { 11 for (int j = 1; j <= n; ++j) { 12 if (p[j - 1] == \'*\') { 13 dp[i][j] = dp[i - 1][j] || dp[i][j - 1]; 14 } else { 15 dp[i][j] = (s[i - 1] == p[j - 1] || p[j - 1] == \'?\') && dp[i - 1][j - 1]; 16 } 17 } 18 } 19 return dp[m][n]; 20 } 21 };
以上是关于LeetCode(44): 通配符匹配的主要内容,如果未能解决你的问题,请参考以下文章