算法技巧总结(四)滑动窗口

这篇博客探讨了滑动窗口的概念及其在字符串匹配问题中的应用。通过双指针实现,滑动窗口可以动态调整大小以找到满足特定条件的子串。文章展示了一个C++实现的示例,用于在字符串中查找所有连续包含给定单词集合的子串。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 滑动窗口字面意思就是这个窗口是移动的,也就是移动是按照一定方向来的。窗口大小并不是固定的,可以不断扩容直到满足一定的条件;也可以不断缩小,直到找到一个满足条件的最小窗口;当然也可以是固定大小。

  • 滑动窗口实际上也算是双指针的应用,同样是由左右指针,右指针的作用是不断扩大窗口的范围,当窗口内的对象符合某个条件时,进行统计或者某种操作;然后左指针作用收缩窗口来打破条件,以便让右指针右移继续扩大窗口

  • 滑动窗口的应用:

在这里插入图片描述

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        //特殊情况直接排除
        if(s.empty()||words.empty())return {};
        
        //存放结果的数组
        vector<int> result;
        
        //单词数组中的单词的大小,个数,以及总长度
        int one_word=words[0].size();
        int word_num=words.size();
        int all_len=one_word*word_num;
        
        //建立单词->单词个数的映射
        unordered_map<string,int> m1;
        for(const auto& w:words)m1[w]++;
        
        for(int i=0;i<one_word;++i)
        {
            //left和rigth表示窗口的左右边界,count用来统计匹配的单词个数
            int left=i,right=i,count=0;
            
            unordered_map<string,int>m2;
            
            //开始滑动窗口
            while(right+one_word<=s.size())
            {
                //从s中提取一个单词拷贝到w
                string w=s.substr(right,one_word);
                right+=one_word;//窗口右边界右移一个单词的长度
                
                if(m1.count(w)==0){//此单词不在words中,表示匹配不成功,然后重置单词个数、窗口边界、以及m2
                    count=0;
                    left=right;
                    m2.clear();
                }
                else{//该单词匹配成功,添加到m2中
                    m2[w]++;
                    count++;    
                    while(m2.at(w)>m1.at(w))//一个单词匹配多次,需要缩小窗口,也就是left右移
                    {
                        string t_w=s.substr(left,one_word);
                        count--;
                        m2[t_w]--;
                        left+=one_word;
                    }
                    if(count==word_num)result.push_back(left);
                }
            }
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值