'?' Matches any single character.
'*' Matches any sequence of characters(including the empty sequence).
The matching should cover the entireinput 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
Given [0,1,0,2,1,0,1,3,2,1,2,1],return 6.
思路:本题与《Regular Expression Matching》类似,解题思路也可以照搬:在模式p中,一旦遇到字符’*’,就将从p+1开始于s+i(i=0,1,2,...)进行匹配,直到找到匹配的位置。但是需要注意一点,如果到了s的最后还是没能匹配的话,整个匹配过程就应该结束了,不应该在回退回去,去看s+i+1是否与p+1匹配,因为是没有意义的,代码如下:
int isMatchcore(char*s, char* p, int *exitflag) { if(*s == ' ') { if(*p == ' ') return 1; if(*p == '*' &&*(p+1) == ' ') return 1; *exitflag = 1; return 0; } if(*p != '*') { if(*p == *s ||*p == '?') returnisMatchcore(s+1, p+1, exitflag); return 0; } if(*p == '*') { if(*(p+1) ==' ') return 1; int i = 0; int slen = strlen(s); while(i < slen &&(isMatchcore(s+i, p+1, exitflag)== 0)) { if(*exitflag == 1) { return 0; } i++; } if(i < slen) return 1; return 0; } } void predealpattern(char*p) { int i = 0; int plen = strlen(p); int j = 0; int lastchar = 0; for(i = 0; i <=plen; i++) { if(p[i] != '*'|| lastchar != '*') { p[j] = p[i]; j++; } lastchar = p[i]; } } int isMatch_recurse(char*s, char* p) { predealpattern(p); int exitflag = 0; return isMatchcore(s, p,&exitflag); }
predealpattern函数用来对模式进行预处理,对于一连串的’*”,比如’****’,只保留一个’*’。这样做是为了减少递归的次数。exitflag的作用就是,一旦匹配到了s的最后还没有匹配成功,则整个匹配过程就应该结束了。开始没有注意到这一点,则在leetcode上测试直接超时。该递归程序最后的测试时间是16ms。下面是非递归版本,原理上是类似的,时间上更快一些,为8ms:
int isMatch_loop(char*s, char* p) { char *lastp = NULL; char *lasts = NULL; while(*s != ' ') { if(*s == *p ||*p == '?') { s++; p++; } else if(*p == '*') { p++; if(*p == ' ') return 1; lastp = p; lasts = s; } else if(lastp != NULL) { p = lastp; s = ++lasts; } else { return 0; } } while(*p == '*')p++; return *p == ' '; }
参考:
https://github.com/haoel/leetcode/tree/master/algorithms/wildcardMatching