力扣算法題—044通配字符匹配
//此為博客講解
//p串中星號的位置很重要,用jStar來表示,還有星號匹配到s串中的位置,
//使用iStart來表示,這裏 iStar 和 jStar 均初始化為 - 1,表示默認情況下是沒有星號的。
//然後再用兩個變量i和j分別指向當前s串和p串中遍歷到的位置。
//
//開始進行匹配,若i小於s串的長度,進行while循環。若當前兩個字符相等,
//或著p中的字符是問號,則i和j分別加1。若p[j] 是星號,那麽我們要記錄星號的位置,
//pStar賦為j,此時j再自增1,iStar賦為i。若當前p[j] 不是星號,並且不能跟p[i] 匹配上,
//那麽此時就要靠星號了,若之前星號沒出現過,那麽就直接跪,比如 s = "aa" 和 p = "c*",
//比如 s = "aa" 和 p = "*c",當發現 s[1] 和 p[1] 無法匹配時,但是好在之前 p[0] 出現了星號,
//我們把 s[1] 交給 p[0] 的星號去匹配。至於如何知道之前有沒有星號,這時就能看出 iStar 的作用了,
//因為其初始化為 - 1,而遇到星號時,其就會被更新為i,那麽我們只要檢測 iStar 的值,
//就能知道是否可以使用星號續命。雖然成功續了命,匹配完了s中的所有字符,但是之後我們還要檢查p串,
//此時沒匹配完的p串裏只能剩星號,不能有其他的字符,將連續的星號過濾掉,如果j不等於p的長度,
1 class Solution { 2 public: 3 bool isMatch(string s, string p) { 4 int i = 0, j = 0, iStar = -1, jStar = -1; 5 while (i < s.size()) { 6 if (s[i] == p[j] || p[j] == ‘?‘) { 7 ++i; ++j; 8 } 9 elseif (p[j] == ‘*‘) { 10 iStar = i; 11 jStar = j++; 12 } 13 else if (iStar >= 0) { 14 i = ++iStar; 15 j = jStar + 1; 16 } 17 else return false; 18 } 19 while (p[j] == ‘*‘) ++j; 20 return j == p.size(); 21 } 22 };
//使用動態規劃
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 } 15 else { 16 dp[i][j] = (s[i - 1] == p[j - 1] || p[j - 1] == ‘?‘) && dp[i - 1][j - 1]; 17 } 18 } 19 } 20 return dp[m][n]; 21 } 22 };
//使用遞歸思想
//有三種不同的狀態,返回0表示匹配到了s串的末尾,但是未匹配成功;
//返回1表示未匹配到s串的末尾就失敗了;返回2表示成功匹配。
//那麽只有返回值大於1,才表示成功匹配。至於為何失敗的情況要分類,
//就是為了進行剪枝。在遞歸函數中,若s串和p串都匹配完成了,返回狀態2。
//若s串匹配完成了,但p串但當前字符不是星號,返回狀態0。若s串未匹配完,
//p串匹配完了,返回狀態1。若s串和p串均為匹配完,且當前字符成功匹配的話,
//對下一個位置調用遞歸。否則若p串當前字符是星號,那麽我們首先跳過連續的星號
//。然後我們分別讓星號匹配空串,一個字符,兩個字符,....,直到匹配完整個s串
//,對每種情況分別調用遞歸函數,接下來就是最大的亮點了,也是最有用的剪枝,
//當前返回值為狀態0或者2的時候,返回,否則繼續遍歷。如果我們僅僅是狀態2的時候才返回,
//因為當返回值為狀態0的時候,已經沒有繼續循環下去的必要了,非常重要的一刀剪枝,參見代碼如下:
1 class Solution { 2 public: 3 bool isMatch(string s, string p) { 4 return helper(s, p, 0, 0) > 1; 5 } 6 int helper(string& s, string& p, int i, int j) { 7 if (i == s.size() && j == p.size()) return 2; 8 if (i == s.size() && p[j] != ‘*‘) return 0; 9 if (j == p.size()) return 1; 10 if (s[i] == p[j] || p[j] == ‘?‘) { 11 return helper(s, p, i + 1, j + 1); 12 } 13 if (p[j] == ‘*‘) { 14 if (j + 1 < p.size() && p[j + 1] == ‘*‘) { 15 return helper(s, p, i, j + 1); 16 } 17 for (int k = 0; k <= (int)s.size() - i; ++k) { 18 int res = helper(s, p, i + k, j + 1); 19 if (res == 0 || res == 2) return res; 20 } 21 } 22 return 1; 23 } 24 };
力扣算法題—044通配字符匹配