【LeetCode】44. Wildcard Matching解法及注释

来源:互联网 发布:中国十大功勋程序员 编辑:程序博客网 时间:2024/06/02 02:21

44. Wildcard Matching

Implement wildcard pattern matching with support for '?' and '*'.
1. '?' Matches any single character.
2. '*' Matches any sequence of characters (including the empty sequence).
3. The matching should cover the entire input string (not partial).
4. 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

【分析】

此题是一个“通配符”匹配问题,给定两个字符串,判断是否匹配,根据题意:字符串s为不包含通配符的普通字符串,字符串p为包含通配符“*”和“?”的字符串,我们需要判断的就是字符串p是否与s匹配,因此,我们需要逐次比较两个字符串的字符。

根据题目给出的examples,我们可以得出一些基本规则:(设ps,pp分别为字符串s和p的下标)

1. 如果s[ps]==p[pp],直接移动下标(pp++;ps++),比较下一个位置的字符是否相等;

2. 如果p[pp]=='?',那么无论对应的s[ps]是什么字符都为所谓,同1的处理一样;

3. 如果p[pp]==‘*’,本题的难点就来了,‘*’可以匹配任何字符和字符串,但它究竟该和s中的哪些或哪些字符匹配,我们需要比较后面的字符,举个例子s="abcacc",p="abc*c",前三个字符都是匹配的,移动下标即可,当ps=pp=3,即s[ps]='a',p[pp]='*'时,我们并不知道‘*’该匹配什么字符,只能根据后面的比较结果来决定,我们移动pp到下一位:p[4]='c',与s[3]不匹配,因此,‘*’需要匹配s[3],即使确定s[3]由p[3]匹配,我们并不能确定p[3]='*'只与s[3]匹配,它可以匹配多个字符,因此我们需要保存‘*’的位置。我们继续移动ps,s[ps]=s[4]='c',此时pp回到为3,同上,我们移动pp,p[pp]=p[4]='c',两者恰好匹配,同时移动pp,ps,发现s[5]!=p[5],这时候,我们需要用到“回溯法”的思想,重新将pp移动到‘*‘的位置3,ps回溯到上一次已经用’*‘匹配过的ps=3的位置的下一位,用pp=3中的’*‘继续匹配ps=4位置的字符,再移动ps。s[ps]=s[5]与p[pp]=p[3]比较,p[3]='*',移动pp,比较下一位,发现p[4]=s[5],同时移动pp,ps,达到字符串s的末尾,循环比较结束。

4. 循环比较结束后,并不能确定p和s匹配,比如s="abcacc",p="abc*cd",我们需要对p进行验证,只有pp同时到达字符串尾端或者p后面剩余的字符全为’*‘如:s="abcacc",p="abc********",才能形成匹配。

【算法及注释】

class Solution {public:   bool isMatch(string s,string p){int LS,LP;//求输入字符串的长度,以便特殊情况的处理LS=s.length();LP=p.length();if(LS==0&&LP==0)return true;//均为空串,返回trueelse if(LS==0&&LP!=0)//s为空,p中全部为'*'则匹配,返回true,否则返回false{int i=0;while(p[i]=='*')i++;if(i==LP)return true;//判断p 中是否全部为'*'else return false;}else{int pp,ps;//记录输入字符串的下标pp=ps=0;//初始化int matchIndex=0;//记录待匹配字符的下标int starIndex=0;//记录上一个'*'出现的下标bool flag=false;//标记是否前面出现过'*'while(ps<LS)//循环控制条件,因为我们是用p去匹配s,因此循环以s为主导,p主动去匹配s{if(s[ps]==p[pp]||p[pp]=='?')//最简单的情况,直接移动下标,比较下一位{pp++;ps++;}else if(p[pp]=='*')//出现'*'{flag=true;//标记'*'出现starIndex=pp;//记录‘*’出现的位置下标matchIndex=ps;//记录待匹配S字符串的字符下标pp++;//这时只移动pp,再与s中的字符比较,从而确定前面的'*'如何匹配}else{if(!flag)return false;//如果对应位置的字符不同,前面也没有出现过'*',说明两者不匹配,返回pp=starIndex;//如果前面出现'*',将pp“回溯”到'*'出现的位置ps=matchIndex;//ps“回溯”到上一次待匹配的字符的下标,进行匹配ps++;//待匹配的s中的字符匹配后,移动ps到下一个位置,继续判断}}while(p[pp]=='*'&&pp<LP)pp++;//待s中的字符被完全匹配后,再对p中的后续字符进行检验,到达末尾或者后面全为'*'if(p[pp]=='\0')return true;else return false;}}};


0 0
原创粉丝点击