1. 题目来源
2. 题目解析
本题是 lc
前 30 道题目中考查算法、思维最有价值的一道题。不论是从复杂度计算,还是想到这个做法,还是算法优化来讲,都是一道非常非常有价值的题目!
参考大佬的:双指针、暴力,应该都可以做。至于字符串哈希应用的话就可以将每次插入字符串进哈希表中的这个 w
消除掉,总的时间复杂度将进一步优化到
O
(
n
)
O(n)
O(n) 。
- 时间复杂度: O ( w n ) O(wn) O(wn)
- 空间复杂度: O ( m ) O(m) O(m)
代码:
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> res;
if (words.empty()) return res;
int n = s.size(), m = words.size(), w = words[0].size();
unordered_map<string, int> tot;
for (auto& e:words) tot[e]++;
for (int i = 0; i < w; ++i) { // 枚举w组
unordered_map<string, int> wd; // 滑动窗口
int cnt = 0;
for (int j = i; j + w <= n; j += w) {
if (j >= i + m * w) { // 窗口满了,将前面的单词删掉
auto word = s.substr(j - m * w, w); // 取得窗口前一个单词
wd[word] --;
if (wd[word] < tot[word]) cnt --; // 减掉的是有效单词
}
auto word = s.substr(j, w); // 找到下一个单词
wd[word] ++; // 添加至滑动窗口哈希表
if (wd[word] <= tot[word]) cnt ++; // 新进来的是有效单词
if (cnt == m) res.push_back(j - (m - 1) * w); // 找到了一个有效答案
}
}
return res;
}
};