- categories: Code, Interview Question, leetcode, Hard
- source: https://leetcode.com/problems/substring-with-concatenation-of-all-words
- topics: Sliding Window, Hash Table
Description
You are given a string s
and an array of strings words
. All the strings of words
are of the same length.
A concatenated string is a string that exactly contains all the strings of any permutation of words
concatenated.
- For example, if
words = ["ab","cd","ef"]
, then"abcdef"
,"abefcd"
,"cdabef"
,"cdefab"
,"efabcd"
, and"efcdab"
are all concatenated strings."acdbef"
is not a concatenated string because it is not the concatenation of any permutation ofwords
.
Return an array of the starting indices of all the concatenated substrings in s
. You can return the answer in any order.
Idea
Sliding window with frequency counter
from collections import defaultdict
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
ans = []
words_dict = defaultdict(int)
found_freq = defaultdict(int)
window_size = len(words[0])
concat_size = window_size * len(words)
for i in range(len(words)):
words_dict[words[i]] += 1
for w in range(window_size):
counter = 0
found_freq.clear()
i = w
while i < len(s) - window_size + 1:
candidate = s[i:i+window_size]
if not candidate in words_dict:
found_freq.clear()
counter = 0
i += window_size
continue
found_freq[candidate] += 1
counter += 1
i += window_size
while found_freq[candidate] > words_dict[candidate] or counter > len(words):
last_word_idx = i - counter * window_size
last_word = s[last_word_idx:last_word_idx + window_size]
counter -= 1
found_freq[last_word] -= 1
if counter == 0:
break
if counter == len(words):
ans.append(i - counter * window_size)
return ans