# [LeetCode] 30. Substring with Concatenation of All Words 串联全部单词的子串

2021年09月15日 阅读数：1

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.html

Example 1:java

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

Example 2:python

```Input:
s = "wordgoodstudentgoodword",
words = ["word","student"]
Output: `[]````

Java:url

```class Solution {
public List<Integer> findSubstring(String s, String[] words) {
final Map<String, Integer> counts = new HashMap<>();
for (final String word : words) {
counts.put(word, counts.getOrDefault(word, 0) + 1);
}
final List<Integer> indexes = new ArrayList<>();
final int n = s.length(), num = words.length, len = words[0].length();
for (int i = 0; i < n - num * len + 1; i++) {
final Map<String, Integer> seen = new HashMap<>();
int j = 0;
while (j < num) {
final String word = s.substring(i + j * len, i + (j + 1) * len);
if (counts.containsKey(word)) {
seen.put(word, seen.getOrDefault(word, 0) + 1);
if (seen.get(word) > counts.getOrDefault(word, 0)) {
break;
}
} else {
break;
}
j++;
}
if (j == num) {
indexes.add(i);
}
}
return indexes;
}
}
```

Python:code

```class Solution(object):
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
result, m, n, k = [], len(s), len(words), len(words[0])
if m < n*k:
return result

lookup = collections.defaultdict(int)
for i in words:
lookup[i] += 1                # Space: O(n * k)

for i in xrange(k):               # Time:  O(k)
left, count = i, 0
tmp = collections.defaultdict(int)
for j in xrange(i, m-k+1, k): # Time:  O(m / k)
s1 = s[j:j+k];            # Time:  O(k)
if s1 in lookup:
tmp[s1] += 1
if tmp[s1] <= lookup[s1]:
count += 1
else:
while tmp[s1] > lookup[s1]:
s2 = s[left:left+k]
tmp[s2] -= 1
if tmp[s2] < lookup[s2]:
count -= 1
left += k
if count == n:
result.append(left)
tmp[s[left:left+k]] -= 1
count -= 1
left += k
else:
tmp = collections.defaultdict(int)
count = 0
left = j+k
return resultv
```

Python:htm

```# Time:  O(m * n * k), where m is string length, n is dictionary size, k is word length
# Space: O(n * k)
class Solution2(object):
def findSubstring(self, s, words):
"""
:type s: str
:type words: List[str]
:rtype: List[int]
"""
result, m, n, k = [], len(s), len(words), len(words[0])
if m < n*k:
return result

lookup = collections.defaultdict(int)
for i in words:
lookup[i] += 1                            # Space: O(n * k)

for i in xrange(m+1-k*n):                     # Time: O(m)
cur, j = collections.defaultdict(int), 0
while j < n:                              # Time: O(n)
word = s[i+j*k:i+j*k+k]               # Time: O(k)
if word not in lookup:
break
cur[word] += 1
if cur[word] > lookup[word]:
break
j += 1
if j == n:
result.append(i)

return result
```

C++:blog

```class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> res;
if (s.empty() || words.empty()) return res;
int n = words.size(), m = words[0].size();
unordered_map<string, int> m1;
for (auto &a : words) ++m1[a];
for (int i = 0; i <= (int)s.size() - n * m; ++i) {
unordered_map<string, int> m2;
int j = 0;
for (j = 0; j < n; ++j) {
string t = s.substr(i + j * m, m);
if (m1.find(t) == m1.end()) break;
++m2[t];
if (m2[t] > m1[t]) break;
}
if (j == n) res.push_back(i);
}
return res;
}
};
```

C++:　　字符串

```class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
if (s.empty() || words.empty()) return {};
vector<int> res;
int n = s.size(), cnt = words.size(), len = words[0].size();
unordered_map<string, int> m1;
for (string w : words) ++m1[w];
for (int i = 0; i < len; ++i) {
int left = i, count = 0;
unordered_map<string, int> m2;
for (int j = i; j <= n - len; j += len) {
string t = s.substr(j, len);
if (m1.count(t)) {
++m2[t];
if (m2[t] <= m1[t]) {
++count;
} else {
while (m2[t] > m1[t]) {
string t1 = s.substr(left, len);
--m2[t1];
if (m2[t1] < m1[t1]) --count;
left += len;
}
}
if (count == cnt) {
res.push_back(left);
--m2[s.substr(left, len)];
--count;
left += len;
}
} else {
m2.clear();
count = 0;
left = j + len;
}
}
}
return res;
}
};
```