30. Substring with Concatenation of All Words

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words)
    {
        // 每個單字的長度都相同,為 n
        int n = words[0].size();

        // 計算總共有幾個單字
        int wordCounts = words.size();

        unordered_map<string,int> freq;

        // 計算每個單字出現的頻率
        for (int i = 0; i < wordCounts; i++)
        {
            freq[words[i]]++;
        }

        vector<int> res;

        // 一個指標 start 走訪一個單字的長度 n
        for (int start = 0; start < n; ++start)
        {
            // 兩個指標 i, j
            // i 為右邊界
            // j 為左邊界
            int i = start;
            int j = i;
            int cnt = 0;

            // 記錄目前的子串中每個單字的出現次數
            unordered_map<string, int> m;

            // 走訪字串 s
            while (j < s.size())
            {
                // 如果子串中出現了一個不在 words 中的單字,清空 m,並且將指針 i 和 j 向前移動一個單字的長度。
                if (!freq.count(s.substr(j, n)))
                {
                    // 清空 m
                    m.clear();
                    // 清空 cnt
                    cnt = 0;
                    // i, j 跳到下一個起始點
                    j += n;
                    i = j;
                }
                // 如果子串中所有單字的出現次數均不超過 words 中該單字的出現次數,我們將指針 j 向前移動一個單字的長度,同時增加相應的計數。
                else if (m[s.substr(j, n)] < freq[s.substr(j, n)])
                {
                    m[s.substr(j, n)]++;
                    cnt++;
                    j += n;
                }
                // 如果子串中某個單字的出現次數超過了 words 中該單字的出現次數,我們將指針 i 向前移動一個單字的長度,同時將相應的計數減少。
                else if (m[s.substr(j, n)] == m[s.substr(j, n)])
                {
                    m[s.substr(i, n)]--;
                    i += n;
                    cnt--;
                }

                // 當找到一個包含 words 中所有單字的子串時,將其起始 index 加入結果 res 中。
                if (cnt == wordCounts)
                {
                    res.push_back(i);
                    m[s.substr(i, n)]--;
                    // i 向前移動 n 的距離
                    i += n;
                    cnt--;
                }
            }
        }

        return res;
    }
};
  • T: O()O()
  • S: O()O()