哈希表 t o t tot tot 存 w o r d s words words 所有单词的出现次数。
维护滑动窗口,窗口长度 m × w m\times w m×w , m m m 是单词数量 w w w是单词长度 , 窗口长度对应可行解的长度。哈希表 w d wd wd 维护滑动窗口内每个单词的出现次数。
维护有效串总数 c n t cnt cnt ,当 c n t = m cnt=m cnt=m 时,找到一个可行解。当右窗口右移,加入的单词是需要的, c n t + + cnt++ cnt++ , 当左窗口右移,移除的单词是需要的, c n t − − cnt-- cnt−− 。 对照 w d wd wd 和 t o t tot tot 判断单词是否需要 。
提示 : 滑动窗口达到最大长度后,维护左窗口。
将 s s s 分成 w w w 组,起点从 0 0 0 到 w − 1 w-1 w−1 ,遍历每一组,得到答案。
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {//字符串哈希
vector<int> ans;
if(words.empty()) return ans;
unordered_map<string,int> tot;
for(auto &x:words) tot[x]++;
int n = s.size(),m = words.size(),w = words[0].size();
for(int i = 0;i<w;i++){
int cnt = 0;
unordered_map<string,int> wd;
for(int j = i ;j<=n;j+=w){
if(j >= i + m*w){//滑动窗口满了,维护左窗口
auto s1 = s.substr(j-m*w,w);
wd[s1]--;
if(tot[s1]>wd[s1]) cnt--;//减去了有效串
}
auto s2 = s.substr(j,w);
wd[s2]++;
if(tot[s2]>=wd[s2]) cnt++;//增加了有效串
if(m == cnt) ans.push_back(j-(m-1)*w);
}
}
return ans;
}
};
理解思路很重要!
欢迎读者在评论区留言,作为日更博主,看到就会回复的。
