15. 串联所有单词的子串
题目描述
给定一个字符串 s 和一些长度相同的单词 words,找出 s 中恰好由 words 中所有单词串联组成的子串的起始索引。
示例
输入: s = "barfoothefoobarman" words = ["foo", "bar"] 输出:[0, 9] 解释:从索引 0 开始是 "barfoo",从索引 9 开始是 "foobar"。
解题思路
这道题的核心在于将'单词'视为整体单位进行滑动窗口处理。如果我们将每个单词看作一个字符,问题就转化为了寻找字符串中的异位词组合。
关键差异点:
- 哈希表的键类型变为
string,用于统计单词频次。 - 左右指针的移动步长不再是 1,而是单词的长度
len。 - 由于起始位置可能落在单词中间,我们需要对
0到len-1分别作为起点进行多次遍历。
代码实现
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 n = s.size();
// 以 0 到 len-1 为起始偏移量分别进行滑动窗口
for(int i = 0; i < len; i++) {
unordered_map<string, int> hash2; // 当前窗口内的单词统计
int count = 0; // 窗口内有效单词个数
int left = i;
( right = i; right + len <= n; 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;
}
};




