---
description: Two Pointer
---

# LeetCode 30. Substring with Concatenation of All Words



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]
```

**Constraints:**

* `1 <= s.length <= 104`
* `s` consists of lower-case English letters.
* `1 <= words.length <= 5000`
* `1 <= words[i].length <= 30`
* `words[i]` consists of lower-case English letters.

## Solution

[English Version in Youtube](https://youtu.be/eebtefMRvjQ)

[中文版解答Youtube Link](https://youtu.be/n9fYwG3dC_Q)

[中文版解答Bilibili Link](https://www.bilibili.com/video/BV1up4y1h7AC/)

```
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> res;
        unordered_map<string, int> dict;
        int len = words[0].size();
        int n = s.length(), m = words.size();
        for (const string& word : words) {
            dict[word]++;
        }
        for (int i = 0; i < len; i++) {
            int cnt = 0;
            unordered_map<string, int> copy = dict;
            for (int j = i; j <= n - len; j += len) {
                string cur = s.substr(j, len);
                copy[cur]--;
                if (copy[cur] >= 0) {
                    cnt++;
                }
                
                int pop_start = j - m * len;
                if (pop_start >= 0) {
                    string pop_word = s.substr(pop_start, len);
                    copy[pop_word]++;
                    if (copy[pop_word] > 0) {
                        cnt--;
                    }
                }
                if (cnt == m) {
                    res.push_back(pop_start + len);
                }
            }
        }
        return res;
    }
};
```
