Hard!
題目描述:
給定一個字符串 (s
) 和一個字符模式 (p
) ,實現一個支持 '?'
和 '*'
的通配符匹配。
'?' 可以匹配任何單個字符。 '*' 可以匹配任意字符串(包括空字符串)。
兩個字符串完全匹配才算匹配成功。
說明:
s
可能為空,且只包含從a-z
的小寫字母。p
可能為空,且只包含從a-z
的小寫字母,以及字符?
和*
。
示例 1:
輸入: s = "aa" p = "a" 輸出: false 解釋: "a" 無法匹配 "aa" 整個字符串。
示例 2:
輸入: s = "aa" p = "*" 輸出: true 解釋: '*' 可以匹配任意字符串。
示例 3:
輸入: s = "cb" p = "?a" 輸出: false 解釋: '?' 可以匹配 'c', 但第二個 'a' 無法匹配 'b'。
示例 4:
輸入: s = "adceb" p = "*a*b" 輸出: true 解釋: 第一個 '*' 可以匹配空字符串, 第二個 '*' 可以匹配字符串 "dce".
示例 5:
輸入: s = "acdcb" p = "a*c?b" 輸入: false
解題思路:
這道題通配符匹配問題還是小有難度的,這道里用了貪婪算法Greedy Alogrithm來解,由於有特殊字符*和?,其中?能代替任何字符,*能代替任何字符串,那么我們需要定義幾個額外的指針,其中scur和pcur分別指向當前遍歷到的字符,再定義pstar指向p中最后一個*的位置,sstar指向此時對應的s的位置,具體算法如下:
- 定義scur, pcur, sstar, pstar
- 如果*scur存在
- 如果*scur等於*pcur或者*pcur為 '?',則scur和pcur都自增1
- 如果*pcur為'*',則pstar指向pcur位置,pcur自增1,且sstar指向scur
- 如果pstar存在,則pcur指向pstar的下一個位置,scur指向sstar自增1后的位置
- 如果pcur為'*',則pcur自增1
- 若*pcur存在,返回False,若不存在,返回True
C語言解法一:
1 bool isMatch(char *s, char *p) { 2 char *scur = s, *pcur = p, *sstar = NULL, *pstar = NULL; 3 while (*scur) { 4 if (*scur == *pcur || *pcur == '?') { 5 ++scur; 6 ++pcur; 7 } else if (*pcur == '*') { 8 pstar = pcur++; 9 sstar = scur; 10 } else if (pstar) { 11 pcur = pstar + 1; 12 scur = ++sstar; 13 } else return false; 14 } 15 while (*pcur == '*') ++pcur; 16 return !*pcur; 17 }
這道題也能用動態規划Dynamic Programming來解,寫法跟之前那道題Regular Expression Matching很像,但是還是不一樣。外卡匹配和正則匹配最大的區別就是在星號的使用規則上,對於正則匹配來說,星號不能單獨存在,前面必須要有一個字符,而星號存在的意義就是表明前面這個字符的個數可以是任意個,包括0個,那么就是說即使前面這個字符並沒有在s中出現過也無所謂,只要后面的能匹配上就可以了。而外卡匹配就不是這樣的,外卡匹配中的星號跟前面的字符沒有半毛錢關系,如果前面的字符沒有匹配上,那么直接返回false了,根本不用管星號。而星號存在的作用是可以表示任意的字符串,當然只是當匹配字符串缺少一些字符的時候起作用,當匹配字符串包含目標字符串沒有的字符時,將無法成功匹配。
C++解法一:
1 class Solution { 2 public: 3 bool isMatch(string s, string p) { 4 int m = s.size(), n = p.size(); 5 vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false)); 6 dp[0][0] = true; 7 for (int i = 1; i <= n; ++i) { 8 if (p[i - 1] == '*') dp[0][i] = dp[0][i - 1]; 9 } 10 for (int i = 1; i <= m; ++i) { 11 for (int j = 1; j <= n; ++j) { 12 if (p[j - 1] == '*') { 13 dp[i][j] = dp[i - 1][j] || dp[i][j - 1]; 14 } else { 15 dp[i][j] = (s[i - 1] == p[j - 1] || p[j - 1] == '?') && dp[i - 1][j - 1]; 16 } 17 } 18 } 19 return dp[m][n]; 20 } 21 };