LeetCode 44 Wildcard Matching
把我难哭了 T T
'?' 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
绞尽脑汁想出来一个方法是使用递归,但是会超时T^T万恶的超时原因很简单,循环里面套用递归,不超时才怪。但是还是把方法粘贴出来:
1 bool satisfyCondition(string p){//判断p是否全由*组成 2 bool satisfy = true; 3 for(int i = 0 ;i < p.length();i++){ //need p to be a form of ?******** 4 if(p[i]!='*'){ 5 satisfy = false; 6 break; 7 } 8 } 9 return satisfy; 10 } 11 12 string getSubStrFromIndexToEnd(string s, int a){//从P尾截取长度为a的串 13 string resultStr = ""; 14 for(int i = a;i < s.length();i++){ 15 resultStr+=s[i]; 16 } 17 return resultStr; 18 } 19 20 21 bool isMatch(string s, string p) { 22 int len1 = s.length(); 23 int len2 = p.length(); 24 bool goodResult = false; 25 if(len1==len2 && len1 == 0) //均空串 26 return true; 27 if(p[0] != '?' && p[0] != '*'){//均普通字符串 28 if(p[0]!=s[0]) 29 return false; 30 else 31 return isMatch(getSubStrFromIndexToEnd(s, 1),getSubStrFromIndexToEnd(p, 1)); 32 } 33 else if(p[0] == '?'){ 34 if (len1 == 0) return false; 35 if (len1==1)//判断?之后的是不是都是* 36 { 37 if (satisfyCondition (getSubStrFromIndexToEnd(p, 1))) 38 return true; 39 else 40 return false; 41 } 42 else 43 return isMatch(getSubStrFromIndexToEnd(s,1),getSubStrFromIndexToEnd(p, 1)); 44 } 45 else{//p[0]=='*' 46 for(int i = len1 ;i>=0;i--){//遇到*则进入循环,用贪心的策略,先假设*可以代替s整个串,来看看行不行(*代替整串则s只剩空,判断空串与p剩下的是否match),不行则假设*可以代替短一点的串,此时s只剩最后一个字符,再与p剩下的match,以此类推,找到一个match的就可以了 47 if(isMatch(getSubStrFromIndexToEnd(s,i),getSubStrFromIndexToEnd(p,1))){ 48 goodResult = true; 49 break; 50 } 51 else 52 goodResult = false; 53 } 54 return goodResult; 55 } 56 }
目前还在想第二种方法。。。。
耗时5小时总算想出来了。。。。
前面一种方法用的递归,下面的方法用的是迭代,要比递归快的多。
bool isMatch(string s, string p) { int len1 = s.length(); int len2 = p.length(); int i = 0; //point to s int j = 0; //point to p bool afterStar = false; int afterStarPosS = 0;// 遇到*时s当前遍历的数字位置索引,这个数会改变 int afterStarPosP = 0;//标记*后的位置索引 if(s == p) return true; while(i<len1){ if(j<len2){ if(s[i]==p[j]||p[j]=='?'){ i++; j++; } else if(s[i]!=p[j] && p[j]!= '?'&& p[j]!= '*' && !afterStar){ return false;//如果从来没遇到过*就碰上不一样的字符则不匹配 } else if(s[i]!=p[j] && p[j]!= '?'&& p[j]!= '*' && afterStar){ j = afterStarPosP;//如果遇到过*,则说明假设*所能替代的字符串不对, //需要把J设置到*后的位置重新开始遍历,并重新设置i的值,afterStarPosS自增可以使下一次重新遍历时i的开始位置加和现在比加一,这样代表*所替代的 字符串长度加一 i = afterStarPosS; afterStarPosS++; } else{// p[j]='*' while(j<len2-1 && p[j+1]==p[j] && p[j]== '*' ) j++;//遇到*则看是不是后面都是*,是则肯定match if(j == len2-1)// all behind are '*' return true; afterStarPosP = j+1;//设置洗的afterStarPosP、S值,能走到这一步说明之前的匹配都成功了 afterStarPosS = i; afterStar = true; j++; } } else{//i<len && j==len2 if(afterStar){//遇到p先走到结尾则说明匹配是不成功的,需要重新设置i,j j = afterStarPosP; i = afterStarPosS; afterStarPosS++; } else//如果之前连*都没碰到就这样了,则肯定错了 return false; } } while(p[j]=='*') j++;//s先到结尾时看p是否都是*,是则true否则false if(j == len2) return true; else return true; }
不容易啊!