复杂度O(w*n),n是s串的长度(s.size()),w是word的长度(words[0].size()),m是有几个word(words.size())
枚举起始位置,理论上O(n)个
算法复杂度O(n/w * w * w),首先分组n/w,哈希插入弹出w,总共有w组 (如果是字符串哈希是O(n)的)
如何判断两个集合相等?两个措施,看集合(哈希表)里单词的数量是不是相等;再引入一个外部变量cnt,统计滑动窗口里有多少单词和tot里的单词相同。(这个变量有两层含义:这个单词在tot里没出现过,不能被统计;即使出现过,wd里出现三次相同单词,tot里出现两次相同单词,不能算作有效数字)
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& word : words) tot[word] ++;
for(int i = 0; i < w; i ++)
{
unordered_map<string, int> wd;
int cnt = 0;
// 滑动窗口的模板要背
for(int j = i; j + w <= n; j += w)
{
// 一开始滑动窗口不足,只能增不能减
// 当超过窗口大小,要把前面的单词删掉
if(j >= i + m * w)
{
// 提取第一个word
auto word = s.substr(j - m * w, w);
wd[word] --;
// 说明是有效单词
if(wd[word] < tot[word]) cnt --;
}
//然后要把word加进去
auto word = s.substr(j, w);
wd[word] ++;
// 说明是有效单词
if(wd[word] <= tot[word]) cnt ++;
// 注意j当前是在最后一个单词上,所以要找第一个单词的下标要(m - 1) * w
if(cnt == m) res.push_back(j - (m - 1) * w);
}
}
return res;
}
};