LeetCode(44): 通配符匹配


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM