1. 程式人生 > >76. minimum-window-substring

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