【LeetCode 76】最小覆盖子串

题目链接

【题解】

尺取法。 用l和r代表一个合法的覆盖子串。 我们不断地扩大右指针。 直到l..r包含T中的所有字母为止(重复的就要两次以上。) 然后我们可以尝试的让l++. 看看新的l..r是不是还是包含所有的字母。 如果是的话。 显然我们得到了一个更优的解。 而且可以肯定。 我们在递增l的时候 不会漏掉比当前更好的解。 因为如果l可以递增缺不递增。 那么从那个位置开始的最短的子串也只能到达r而已。 不会比l递增之后的结果更优。 因此这个算法是成立的。 判断是否包含所有的字母。 只要用个map来存储每个字母出现的次数就好了。(T字符串中的字母) 然后当r递增的时候。 令map[s[r]]-- 如果让s[r]递减的时候第一次变成了0 就说明[l..r]这一段s[r]这个字母出现的次数已经满足了要求。

【代码】

class Solution {
public:
    string minWindow(string s, string t) {
        map<char,int> dic;dic.clear();
        int goal = 0;
        for (int i = 0;i<(int)t.size();i++) {
            dic[t[i]]++;
            if (dic[t[i]]==1) goal++;
        }        
        int l = 0;int cnt = 0;
        int ll = -1,rr=-1;
        for (int r = 0;r<(int)s.size();r++){
            dic[s[r]]--;
            if (dic[s[r]]==0) cnt++;
            if (cnt==goal){
                while((l+1)<=r){
                    if (dic[s[l]]<0){
                        dic[s[l]]++;
                    }else break;
                    l++;
                }
                if (ll==-1){
                    ll = l,rr = r;
                }else{
                    if (rr-ll+1>r-l+1){
                        ll = l;rr = r;
                    }
                }
            }
            
        }
        string anss = "";
        for (int i = ll;i<=rr;i++){
            anss = anss + s[i];
        }
        return anss;
    }
};
原文地址:https://www.cnblogs.com/AWCXV/p/11919043.html