# 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;
}
};
```