1. 程式人生 > >30.substring-with-concatenation-of-all-words

30.substring-with-concatenation-of-all-words

        說實在的,這道題還是比較難的,因為沒有好的思路,其實從歷年各個公司的演算法真題來看,難題還是多出現在字串上,這道題就是比較靈活的一道,沒啥太好的思路,起初想著dfs,倒是可以做,但是開銷蠻大的,因此,這裡我參考大神的程式碼寫了使用hash來解決問題。達到O(N)的時間複雜度和O(N)的空間複雜度。

         題目的大意是給定一個字串和一個字串對應的陣列,在字串中尋找一個字串,該字串正好包含字串陣列中所有的字串,如果字串陣列中有重複,對應的字元子串中也應該有幾個。舉了例子,字串陣列中如果是:{"word", "word"},對應的字串也應該是"wordword"才可以。另外題目中還有一個重要的條件,字串陣列中每個字串的長度是相等的,這對我們的後續工作很重要。返回符合條件的字串的起始位置座標。

         因為字串陣列中每一個字串長度相等,假設長度為k,那麼我們第一次就可以檢測0~k-1,k~2k-1,……,第二次就可以檢測1~k, k+1~2k, ……, …… ,第k次就可以檢測k-1~2k-2,……,而每一次檢測,對應的步長都是k,字串總長度是N,兩層迴圈,一層是k,另一層是N/k,所以,時間複雜度就是O(N).

         思路是這樣的,因為要尋找的字元子串,也就要求我們尋找的目標串連續的,那整個尋找的過程類似於滑動視窗。如果能理解是滑動視窗了,那接下來我們要面對的是兩種情況,

<1>,如果我們當前匹配的字串發生失配的情況,那一定要從當前位置重新開始計數。

<2>,如果字串出現某個單詞個數比原陣列中的多時,我們需要滑動視窗的左邊界向右,將多餘的單詞之前的字串都要捨棄。

以下是AC的程式碼:

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> res;
        if (words.size()<1 || (s.size()<(words.size()*words[0].size()))) {
            return res;
        }
        int wordslen = words.size(), wordsize = words[0].size();
        unordered_map<string, int> unmap1;
        for (string str : words) {
            ++unmap1[str];
        }

        for (int i=0; i<wordsize; ++i) {
            unordered_map<string, int> unmap2;
            int left = i, count = 0;
            for (int j=i; j<=s.size()-wordsize; j+=wordsize) {
                if (unmap1.count(s.substr(j, wordsize))) {
                    ++unmap2[s.substr(j, wordsize)];
                    ++count;
                    while (unmap2[s.substr(j, wordsize)] > unmap1[s.substr(j, wordsize)]) {
                        --unmap2[s.substr(left, wordsize)];
                        left += wordsize;
                        --count;
                    }
                } else {
                    count = 0;
                    left = j+wordsize;
                    unmap2.clear();
                }
                
                if (count == wordslen) {
                    res.emplace_back(left);
                    --unmap2[s.substr(left, wordsize)];
                    left += wordsize;
                    --count;
                }
            }
        }
        return res;
    }
};