串联所有单词的子串
题目要求
给定一个字符串 s 和一个字符串数组 words。其中 words 中的所有单词长度相同。找出 s 中所有由 words 中所有单词以任意顺序连接而成的子串的起始索引。
解题思路
这道题的核心在于将'单词'视为整体进行滑动窗口操作,而不是单个字符。如果我们将每个单词看作一个字符,问题就转化为了寻找字符串中特定字母的异位词组合。
有几个关键点需要注意:
- 哈希表统计:我们需要用哈希表记录
words中每个单词出现的频次。 - 步长控制:左右指针的移动步长不再是 1,而是单词的长度
len。 - 多次遍历:由于起始位置可能不同(例如从第 0 个字符开始,或者从第 1 个字符开始),我们需要执行
len次滑动窗口过程,确保不遗漏任何可能的起始偏移量。
在窗口扩展时,我们检查当前单词是否在目标集合中且数量未超标;当窗口大小超过总长度时,需要收缩左边界并更新计数。当满足条件的单词数等于 words 总数时,记录当前左边界。
C++ 代码实现
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> ret;
if (words.empty() || s.empty()) return ret;
unordered_map<string, int> hash1; // 保存 words 里面所有单词的频次
for (auto &word : words) hash1[word]++;
int len = words[0].size();
int m = words.size();
int totalLen = len * m;
// 执行 len 次,处理不同的起始偏移
for (int i = 0; i < len; i++) {
unordered_map<string, int> hash2; // 维护窗口内单词的频次
int count = ;
( left = i, right = i; right + len <= s.(); right += len) {
string inWord = s.(right, len);
hash2[inWord]++;
(hash(inWord) && hash2[inWord] <= hash1[inWord]) {
count++;
}
(right - left + > totalLen) {
string outWord = s.(left, len);
(hash(outWord) && hash2[outWord] <= hash1[outWord]) {
count--;
}
hash2[outWord]--;
left += len;
}
(count == m) {
ret.(left);
}
}
}
ret;
}
};


