天天看點

76. minimum-window-substring

       這道題細節處理起來還是有點難度,太不是難到沒有思路的那種。

       題目大意:給定兩個字元串,一個是原始比對串,另一個是目标串,在比對串中選尋找一個最短的字串,包含目标串的所有字元,重複情況要考慮。例如: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;
    }
};