LeetCode 30. 串联所有单词的子串

本文介绍了一种使用哈希表实现的子串查找算法,该算法能在O(n/w*w*w)的时间复杂度内找出所有目标单词在给定字符串中的起始位置。通过滑动窗口和哈希表统计的方式,确保了算法的高效性和准确性。

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

复杂度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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值