leetcode 30. Substring with Concatenation of All Words

sliding window来优化这个遍历过程。保证sliding window里面的单词都是候选词向量里面的词,而且每个候选词只能出现一次。这样的话当sliding window里面的大小与候选词向量的单词数相等的时候,就说明sliding window就是一种合理的答案。用一个哈希表记录候选词向量里每个词的个数,在遍历原字符串的时候,如果下一个单词是在候选词向量里面的,而且在sliding window里面出现的次数没有超过哈希表记录的次数,就可以扩大这个sliding window这种是最理想的情况,一直增大sliding window,直到这个sliding window的大小等于候选词的数量,就把这时候的start index记录下来。但是事情不会总是这么完美的,当遇到不是候选词的单词,说明sliding windowstart index不是一种合理答案,就要清空这个sliding window并且sliding windowstart index向右移一位;还有一种情况是跟单词的次数有关的,当遇到一个候选词w,但是sliding window里面的w出现的次数已经超过了哈希表记录的次数,说明这时的sliding window不是一种合理答案,不能继续扩大sliding window,但这时候是不是和上面的这种情况一样,直接清空sliding window,并右移start index呢?如果将这两种情况合在一起考虑的话,就跟最朴素的查找是一样的了。

这里利用sliding window,每一次遍历都要考虑到直到原字符串最后一个字符的所有的情况。所以startInd = 0startInd = wordLen的分词结果是相同的,startInd = wordLen里所有的合理情况在startInd = 0已经被涵盖了。所以外循环的大小只是wordLen - 1这样的话,当遇到一个候选词w,但是sliding window里面的w出现的次数已经超过了哈希表记录的次数,说明startInd已经不可能是一种合理答案了,但是startInd + x * wordLen还有可能是一种合理答案,这时候要把sliding window的左边界往右移,缩小sliding window的大小。

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if (words.size() == 0 || s == "") {
            return {};
        }
        vector<int> resultVec;
        unordered_map<string, int> hashTable;
        for (int i = 0; i < words.size(); i++) {
            if (hashTable.find(words[i]) == hashTable.end()) {
                hashTable[words[i]] = 0;
            }
            hashTable[words[i]]++;
        }
        int wordLen = int(words[0].length()), wordCount = 0, vectorSize = int(words.size());
        unordered_map<string, int> counterTable;
        for (int i = 0; i < wordLen; i++) {
            int startInd = i;
            counterTable.clear();
            wordCount = 0;
            for (int j = startInd; j < s.length(); j += wordLen) {
                string checkStr = s.substr(j, wordLen);
                if (hashTable.find(checkStr) == hashTable.end()) {
                    counterTable.clear();
                    wordCount = 0;
                    continue;
                } else {
                    if (counterTable.find(checkStr) == counterTable.end()) {
                        counterTable[checkStr] = 0;
                    }
                    counterTable[checkStr]++;
                    wordCount++;
                    while (counterTable[checkStr] > hashTable[checkStr]) {
                        string startSub = s.substr(j - (wordCount - 1) * wordLen, wordLen);
                        counterTable[startSub]--;
                        wordCount--;
                        if (counterTable[startSub] == 0) {
                            counterTable.erase(startSub);
                        }
                    }
                    if (wordCount == vectorSize) {
                        resultVec.push_back(j - (wordCount - 1) * wordLen);
                    }
                }
            }
        }
        return resultVec;
    }
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章