15. 串联所有单词的子串
这道题的核心在于将每个单词视为一个整体字符,问题转化为寻找字符串中所有单词的异位词组合。相比常规字符处理,这里有几个关键点需要注意。
算法思路
- 哈希表结构:使用
unordered_map<string, int>统计目标单词列表中的频次。 - 步长控制:
left和right的移动步长固定为单词长度len,而非单个字符。 - 循环次数:由于起始位置可能落在单词中间,需要执行
len次滑动窗口遍历,确保不遗漏任何可能的起始偏移。
C++ 实现
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> ret;
unordered_map<string, int> hash1; // 统计 words 中所有单词出现的频次
for(auto e : words) {
hash1[e]++;
}
int len = words[0].size(); // 单词长度
int m = words.size(); // 单词数量
int left = 0;
int right = 0;
// 执行 len 次遍历,覆盖所有可能的起始偏移
for(int i = 0; i < len; i++) {
unordered_map<string, int> hash2; // 当前窗口的单词计数
int count = 0; // 窗口中有效单词个数
left = i;
// 注意 size_t 与 int 运算时的类型转换风险
for(right = i; right + len <= ()s.(); right += len) {
string str1 = s.(right, len);
hash2[str1]++;
(hash2[str1] <= hash1[str1]) {
count++;
}
(right - left + > len * m) {
string str2 = s.(left, len);
(hash2[str2] <= hash1[str2]) {
count--;
}
hash2[str2]--;
left += len;
}
(count == m) {
ret.(left);
}
}
}
ret;
}
};




