[leetcode] Wildcard matching——程式設計菜鳥們絕對值得一看
阿新 • • 發佈:2019-02-05
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
class Solution { public: bool isMatch(const char *s, const char *p) { // Start typing your C/C++ solution below // DO NOT write int main() function int i , j, k; int lengths,lengthp; i=j=k=lengths=lengthp=0; lengths=strlen(s); lengthp=strlen(p); if(lengths==0 && lengthp==0) return true; if(lengthp==1){ if(*p=='*') return true; else if(*p=='?'){ if(lengths==1) return true; else return false; } else{ if(lengths==1) return *s==*p; else return false; } }else{ if(*p=='?') return isMatch(++s,++p); else if(*p=='*'){ for(j=0 ; j<lengthp ; j++){ k|=isMatch(s+j,++p); } return k; } else{ if(*s==*p) return isMatch(++s,++p); else return false; } } } };
上面這個遞迴是我自己寫的,思路很簡單了,主要分為以下幾個關鍵的部分:
1. 當遇到?時,那麼可以匹配任意的源字串中的一個字元,我們只需遞迴的匹配下一個萬用字元串和下一個源字串。
2. 當遇到*時,那麼可以匹配任意的源字串,那麼我們就從0個字元開始遞迴匹配。
3. 最簡單的是普通字元,那麼直接匹配,再匹配下面的字串。
發現一個不錯的連結:
這裡面介紹了一些不錯的萬用字元匹配的演算法,看了看他寫的比我好多了!!!自己的程式碼確實跟屎一樣。然後我就稍微把他的程式碼更改了一下,他似乎是一個極其熱愛和平的人,哈哈哈哈:
class Solution { public: bool isMatch(const char *s, const char *p) { // Start typing your C/C++ solution below // DO NOT write int main() function while(*p){ switch(*p){ case '?': // if(*s=='') if(*s)return isMatch(++s,++p); else return false; break; case '*': for(p++;*p!='*';p++); if(!*p)return true; while(*s)if(isMatch(s++,p))return true; return false; default: if(*s!=*p)return false; break; } p++,s++; } for(;*p=='*';p++); return ((!*p)&&(!*s)); } };
這程式碼用到了遞迴,是不能通過大資料的。當然如果你認為這種程式碼就已經夠簡潔的話那你就圖樣圖森破了。程式碼可以簡潔到下面這個樣子:
class Solution {
public:
bool isMatch(const char *s, const char *p) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
switch(*p){
case '\0':
return !*s;
case '*':
return isMatch(s,p+1) || *s && isMatch(s+1,p);
case '?':
return *s && isMatch(s+1,p+1);
default:
return (*s==*p) && isMatch(s+1,p+1);
}
}
};
上面的都是遞迴的解法,遞迴的解法效率永遠是硬傷!下面介紹非遞迴的解法:
class Solution {
public:
bool isMatch(const char *s, const char *p) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int i,star;
new_segment:
star=0;
if(*p=='*'){
star=1;
for(p++;*p=='*';p++);
}
test_match:
for(i=0 ; p[i] && (p[i]!='*');i++){
if(s[i]!=p[i]){
if(!s[i])return false;
if((p[i]=='?') && s[i]) continue;
if(!star)return false;
s++;
goto test_match;
}
}
if(p[i]=='*'){
s+=i;
p+=i;
goto new_segment;
}
if(!s[i])return true;
if(i && p[i-1]=='*') return true;
if(!star) return false;
s++;
goto test_match;
}
};
這裡面用到了goto語句,我會考慮將goto去除的