這道題細節處理起來還是有點難度,太不是難到沒有思路的那種。
題目大意:給定兩個字元串,一個是原始比對串,另一個是目标串,在比對串中選尋找一個最短的字串,包含目标串的所有字元,重複情況要考慮。例如:abdccab 目标串是 abccd,則原始比對串中最短的字元串是dccab
思路,首先,并不是KMP求目标子串,條件沒有那麼嚴格,是以,先要記錄目标串中每個字元的個數。
其次,利用一前一後兩個指針分别表示視窗的左右兩個邊,當比對串left和right中間的字段沒有完全包含目标串中的所有字元,則right指針右移,否則,left指針左移,以獲得最小視窗。
需要注意的是,在視窗的滑動過程中,當某個字元出現在視窗裡面,則說明該字元已經被包含,相應的記錄值要減去1,如果left增加,某個字元從視窗中出去,則該字元的計數值要加1,表示該字元已經不在記錄中了。這塊說起來可能不要說清楚,看代碼一下就明白了。
另外,這道題是用hash表來做是非常友善的,但是,告訴大家一個小技巧,所有的和字元串相關的問題,凡是用到hash表做計數用的,都可以轉化為使用數組。
以下是AC的代碼:
class Solution {
public:
string minWindow(string s, string t) {
vector<int> tmap(128, 0);
for (char c : t) {
++tmap[c];
}
string res = "";
int counts = 0, minwin = INT_MAX, left = 0;
for (int i=0; i<s.size(); ++i) {
--tmap[s[i]];
if (tmap[s[i]] >= 0) {
++counts;
}
while (counts == t.size()) {
if (minwin > i-left+1) {
minwin = i-left+1;
res = s.substr(left, minwin);
}
if (tmap[s[left]] >= 0) {
--counts;
}
++tmap[s[left]];
++left;
}
}
return res;
}
};