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;
}
   

不容易啊!

posted @ 2016-03-25 09:08  熊阳  阅读(325)  评论(0编辑  收藏  举报