天天看点

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