---
# System prepended metadata

title: Leetcode 解題速記 30. Substring with Concatenation of All Words
tags: [C++, LeetCode]

---

# Leetcode 解題速記 30. Substring with Concatenation of All Words
###### tags: `LeetCode` `C++`
題敘:
---
You are given a string s and an array of strings words of the same length. Return all starting indices of substring(s) in s that is a concatenation of each word in words exactly once, in any order, and without any intervening characters.

You can return the answer in any order.

 

Example 1:

```
Input: s = "barfoothefoobarman", words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoo" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
```

Example 2:

```
Input: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
Output: []
```

Example 3:

```
Input: s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
Output: [6,9,12]
```

測資範圍:
---
* `1 <= s.length <= 104`
* `1 <= words.length <= 5000`
* `1 <= words[i].length <= 30`
* `s and words[i] consist of lowercase English letters.`

解題筆記:
---
這題子字串我們使用的解題方式是slide window，並且用雙指針實現。

首先，我們需要hashmap去記錄當前所有子字串還未被使用的次數，因此開頭先由一個迴圈將word中所有可用的字都記錄進去。

接下來檢查字串的部分，window的寬度跟子字串寬度相同，一次向右移動一個字元。
假設子字串長度為3，s的長度為24，我們第一次檢查的index是0,3,6,9,12,15,18,21，第二次檢查的index就是1,4,7,10,13,16,19，以此類推，剩餘長度不足子字串長度時終止，

每當檢查到一個合法子字串，就將hashmap中相應的值-1，同時，如果hashmap中，該子字串剩餘可用次數>=0時，代表我們沒有用超過可用次數，因此紀錄合法子字串的變數count要+1。

每次迭代中，若是檢查到window的寬度過大，就要將左指針向右移。因此，右移過程中丟到的子字串，也要將相應hashmap中使用次數+1回去，同時，若是剩餘使用次數大於0，代表還沒滿足將所有子字串都使用的條件，因此count要-1。

最後一直迭代到count與words中合法子字串的數量相同，就代表這是一個合法組合，紀錄該組合的起始index，放進vector中統一回傳。

程式碼:
---
``` cpp
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ans;
        unordered_map<string, int> m1;
        int len = words[0].size();
        int n = s.length();
        int m = words.size();
        for (const string& it : words)
        {
            m1[it]++;
        }
        for (int i = 0; i < len; i++)
        {
            int count = 0;
            unordered_map<string, int> temp = m1;
            for (int j = i; j <= n - len; j += len)
            {
                string current = s.substr(j, len);
                temp[current]--;
                if (temp[current] >= 0)
                {
                    count++;
                }

                int pop_start = j - m * len;
                if (pop_start >= 0)
                {
                    string pop_word = s.substr(pop_start, len);
                    temp[pop_word]++;
                    if (temp[pop_word] > 0)
                    {
                        count--;
                    }
                }
                if (count == m)
                {
                    ans.push_back(pop_start + len);
                }
            }
        }
        return ans;
    }
};
```
