[Leetcode] Wildcard matching 通配符匹配

时间:2022-09-01 20:47:52

Implement wildcard pattern matching with support for'?'and'*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

这题和正则表达式匹配有点类似,' . '和本题中的' ? '一样,区别在于' * ',在正则表达式那题中,' * '可以表示之前字符的0个或多个;本题中,可以表示任意字符串。好吧,做了,第一次做的时候,没有完全搞懂,这次出问题了,又去网上找帮助了。本文章参考了peerlessbloom 、点缀星辰Grandyang

思路:当*s ==*p || *p=='? '时,对应的指针分别++即可;当遇到字符' * '时,该怎么办呢?是否像正则表达式那题中的思路把 *s和*(p+1)去比较了?若是这样的,说明没有理解清楚:题目中' * '可以表示任意字符串的含义,举个例子来说明s=" aacabacd "和 p=" a*acd ",这种情况下,若是按上题中的思想,则要返回false,但是本题这种情况确是匹配的。这题中,' * '和' acab '匹配了。这如何实现的了?我们先看*号匹配的几种情况(例子来自 点缀星辰的博客,这里只是结合自己的语言给出了):

 1)*号匹配了串 s 中间指定点秩后所有的字符。这里*号匹配了“bcac”。

[Leetcode] Wildcard matching  通配符匹配

 2)*号匹配部分串的情况。这里*号匹配了“bc”。这种情况就是字符串p中的*号之后的字符' a '和*号对应的S中的字符' b '去匹配,若不匹配,则比较s 中的下一个,直到匹配。

[Leetcode] Wildcard matching  通配符匹配

那是否所有的情况就结束了?如果是这样的,就和正则表达式的那种情况,很相似了,好吧,我当时就是这么想的,错了。还有其他的情况,如:

 3)如下图1,刚开始,*号的下一个和*号对应的S中的字符' a '匹配,这意味着*号代表0个字符,直到' d '和 ' b '不匹配,那这种情况,怎么办了?是否返回false?这种情况显然不会返回false,因为,图中绿色的部分是匹配的,这也说明了一个问题,就是*号代表0个字符这种形式是不对了。那该如何?接下来应该如图2所示,p中字符a跟s中字符c 对比,不匹配,再跟s中字符b对比,直到在s中遇到字符a,即匹配,这样,p和s同时的比较下一个字符。若后面还有*号,能遍历到*号,说明*号之前都是匹配的,这样只要重复上述过程即可。

[Leetcode] Wildcard matching  通配符匹配        

图1

 [Leetcode] Wildcard matching  通配符匹配

图2

这就遇到一个问题了?当匹配了若干字符之后,才发现不匹配,如情况3),这时如何像上述过程那样,比较p中*号的下一位和s中*号对应的那位的下一位了?这时,我们采取的方法是,当遇到*号时,我们将使用两指针记录下此时的值,若在以后的对比中,遇到不匹配的情况,即可返回。当然,p中*号的位置是相对不变的(直到遇到下一*号),而s中用来的对比字符是在变化的。代码如下:

 1 class Solution {
2 public:
3 bool isMatch(const char *s, const char *p)
4 {
5 const char *preS=NULL; //用来记录位置
6 const char *preP=NULL;
7
8 while(*s)
9 {
10 if(*p=='?' || *p==*s)
11 {
12 p++;
13 s++;
14 }
15 else if(*p=='*')
16 {
17 preS=s;
18 preP=p++;
19 }
20 else if(preP) //后面遇到不匹配的情况,则返回重新比较情况3)
21 {
22 p=preP+1;
23 s=++preS;
24 }
25 else
26 return false;
27 }
28 while(*p=='*')
29 p++;
30 return !*p;
31 }
32 };