30. 串联所有单词的子串
Difficulty
Hard
Tags
滑动窗口
URL
https://leetcode.cn/problems/substring-with-concatenation-of-all-words/
Star
给定一个字符串
s
和一些 长度相同 的单词 words
。找出 s
中恰好可以由 words
中所有单词串联形成的子串的起始位置。注意子串要与
words
中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words
中单词串联的顺序。示例 1:
输入:s = "barfoothefoobarman", words = ["foo","bar"] 输出:[0,9]解释: 从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。 输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"] 输出:[]
示例 3:
输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"] 输出:[6,9,12]
提示:
1 <= s.length <= 10
4
s
由小写英文字母组成
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i]
由小写英文字母组成
##滑动窗口
思路
指定移动步长+指定开始位置
最重要的条件「长度相同」,暗示滑动窗口移动的步长 stride 为 len(words[0])
窗口的长度应为 words.size() * stride
当前窗口的长度计算公式为 right - left + stride
需要指定不同的起始位置,起始位置可选范围为 [0, stride-1]
题解
class Solution: def findSubstring(self, s: str, words: List[str]) -> List[int]: length = len(words[0]) need = Counter(words) res = [] # 遍历不同的起点 for start in range(0, length): wds = collections.defaultdict(int) valid = 0 left, right = start, start while right < len(s)-length+1: cur_word = s[right:right+length] right += length if cur_word in need: wds[cur_word] += 1 if wds[cur_word] == need[cur_word]: valid += 1 # 窗口超过限制了,收缩 while right - left > length * len(words): delet_word = s[left:left+length] left += length if delet_word in need: if wds[delet_word] == need[delet_word]: valid -= 1 wds[delet_word] -= 1 if valid == len(need): res.append(left) return res
还有一种收缩窗口的方式,参考 438. 找到字符串中所有字母异位词
class Solution: def findSubstring(self, s: str, words: List[str]) -> List[int]: res = [] need = Counter(words) # 遍历不同的起点 for i in range(0, len(words[0])): l, r = i, i valid = 0 wds = collections.defaultdict(int) while r <= len(s): if r + len(words[0]) - 1 >= len(s): break cur_word = s[r:r+len(words[0])] r += len(words[0]) if cur_word in need: wds[cur_word] += 1 if wds[cur_word] == need[cur_word]: valid += 1 while valid == len(need): if (r - l) // len(words[0]) == len(words): res.append(l) delet_word = s[l:l+len(words[0])] l += len(words[0]) if delet_word in need: if wds[delet_word] == need[delet_word]: valid -= 1 wds[delet_word] -= 1 return res