30. Substring with Concatenation of All Words

滑动窗口

初次尝试失败,会超时,213/230,准备看源码

class Solution {
private:
    bool mapEqual(map<string, int> mp1, map<string, int> mp2){
        map<string, int>::iterator iter1, iter2;
        for(iter1 = mp1.begin(); iter1 != mp1.end(); iter1++){
            iter2 = mp2.find(iter1->first);
            if(iter2 == mp2.end() || iter2->second != iter1->second){
                return false;
            }
        }
        return true;
    }
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> res;
        if(s.size() == 0 || words.size() == 0){
            return res;
        }
        int wordLen = words[0].size();
        int windowsLen = words[0].size() * words.size();
        map<string, int> wordMap;
        map<string, int>::iterator iter;
        for(int i = 0; i < words.size(); i++){
            iter = wordMap.find(words[i]);
            if(iter == wordMap.end()){
                wordMap.insert(pair<string, int>(words[i], 1));
            }
            else{
                iter->second++;
            }
        }
        for(int i = 0; i + windowsLen - 1 < s.size(); i++){
            string sub = s.substr(i, windowsLen);
            map<string, int> windowMap;
            map<string, int>::iterator iter2;
            for(int j = 0; j < sub.size(); j+=wordLen){
                string word = sub.substr(j, wordLen);
                iter2 = windowMap.find(word);
                if(iter2 == windowMap.end()){
                    windowMap.insert(pair<string, int>(word, 1));
                }
                else{
                    iter2->second++;
                }
            }
            // wordMap 和 windowMap 比较
            bool eql = mapEqual(windowMap, wordMap);
            if(eql){
                res.push_back(i);
            }
        }
        return res;
    }
};

再次查看参考代码,原来对滑动窗口的理解有误,重新写

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> res;
        if(s.size() == 0 || words.size() == 0){
            return res;
        }
        int wordLen = words[0].size();
        int wordNum = words.size();
        int windowsLen = words[0].size() * words.size();
        map<string, int> wordMap;
        map<string, int>::iterator iter;
        // 初始化 wordMap
        for(int i = 0; i < words.size(); i++){
            iter = wordMap.find(words[i]);
            if(iter == wordMap.end()){
                wordMap.insert(pair<string, int>(words[i], 1));
            }
            else{
                iter->second++;
            }
        }
        
        // 滑动窗口,累积 wordLen 次
        for(int t = 0; t < wordLen; t++){
            map<string, int> windowMap;
            map<string, int>::iterator iter2, tmp;
            int left = t, right = t, cnt = 0;
            while(right + wordLen <= s.size()){
                // 取出右端进入的 Word, 判断其是否在 Words 中
                string w = s.substr(right, wordLen);
                right += wordLen;
                iter = wordMap.find(w);
                if(iter == wordMap.end()){
                    // 不在,当前滑动窗口无效,移动左端
                    left = right;
                    cnt = 0;
                    windowMap.clear();
                }
                else{
                    // 在,将 windowMap 的对应数量+1
                    iter2 = windowMap.find(w);
                    if(iter2 == windowMap.end()){
                        windowMap.insert(pair<string, int>(w, 1));
                        iter2 = windowMap.find(w);
                    }
                    else{
                        iter2->second++;
                    }
                    cnt++;
                    // 判断是否超数,若超了,从滑动左端依次右移取词并减少其数量,直到满足不超数
                    while(iter2->second > iter->second){
                        string tmpStr = s.substr(left, wordLen);
                        left += wordLen;
                        tmp = windowMap.find(tmpStr);
                        if(tmp != windowMap.end()){
                            tmp->second--;
                        }
                        cnt--;
                        //iter2 = windowMap.find(w);
                    }
                    // 若 cnt 相等,则当前滑动窗口满足
                    if(cnt == wordNum){
                        res.push_back(left);
                    }
                }

            }
        }
        return res;
    }
};