題目
給定一個字符串 (s) 和一個字符模式 § ,實現一個支持 ‘?’ 和 ‘*’ 的通配符匹配。
‘?’ 可以匹配任何單個字符。
‘*’ 可以匹配任意字符串(包括空字符串)。
兩個字符串完全匹配纔算匹配成功。
說明:
- 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
算法實現:一、遞歸
遇到’*'就窮舉,最後超時了
class Solution {
public:
bool isMatch(string s, string p) {
return help(s, p, 0, 0);
}
bool help(string s, string p, int i, int j) {
if (i == s.size() && j == p.size()) return 1;
else if (j == p.size()) return 0;
else if (p[j] == '*')
return help(s, p, i, j + 1) || (i != s.size() && help(s, p, i + 1, j));
else if (p[j] == '?')
return i != s.size() && help(s, p, i + 1, j + 1);
else
return s[i] == p[j] && help(s, p, i + 1, j + 1);
}
};
結果
二、雙指針貪心算法
class Solution {
public:
bool isMatch(string s, string p) {
int i = 0, j = 0, iStar = -1, jStar = -1, m = s.size(), n = p.size();
while (i < m) {
if (j < n && (s[i] == p[j] || p[j] == '?')) {
++i, ++j;//i,j向後瞬移
} else if (j < n && p[j] == '*') {//記錄如果之後序列匹配不成功時, i和j需要回溯到的位置
iStar = i;//記錄星號
jStar = j++;//記錄星號 並且j移到下一位 準備下個循環s[i]和p[j]的匹配
} else if (iStar >= 0) {//發現字符不匹配且沒有星號出現 但是istar>0 說明可能是*匹配的字符數量不對 這時回溯
i = ++iStar;//i回溯到istar+1 因爲上次從s串istar開始對*的嘗試匹配已經被證明是不成功的(不然不會落入此分支) 所以需要從istar+1再開始試 同時inc istar 更新回溯位置
j = jStar + 1;//j回溯到jstar+1 重新使用p串*後的部分開始對s串istar(這個istar在上一行已經inc過了)位置及之後字符的匹配
} else return false;
}
while (j < n && p[j] == '*') ++j;//去除多餘星號
return j == n;
}
};