[LeetCode解题报告] 30. 串联所有单词的子串

该博客详细介绍了如何利用滑动窗口算法解决LeetCode上的30题——串联所有单词的子串。作者通过分析题目,提出将问题转化为处理字母异位词的思路,并给出了复杂度为O(n×d)的解决方案。代码实现中,通过维护窗口内单词计数,判断是否与目标words匹配,从而找到所有满足条件的子串起始位置。博客内容详实,适合对滑动窗口算法和字符串处理感兴趣的读者。
摘要由CSDN通过智能技术生成

一、 题目

1. 题目描述

  1. 串联所有单词的子串

难度:困难

给定一个字符串 s** 和一些 长度相同 的单词 words找出 s 中恰好可以由 words **中所有单词串联形成的子串的起始位置。

注意子串要与 words** **中的单词完全匹配,**中间不能有其他字符 ,但不需要考虑 words **中单词串联的顺序。

示例 1:

输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。

示例 2:

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]

示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成
  • 1 <= words.length <= 5000
  • 1 <= words[i].length <= 30
  • words[i] 由小写英文字母组成

2. 原题链接

链接: 30. 串联所有单词的子串

二、 解题报告

1. 思路分析

这题是 438. 找到字符串中所有字母异位词的加强版,区别是单位从字母变成单词。都可以用滑窗做。

  • 这里由于words中每个单词长度相同,设为d,只需要控制滑窗右移时,每次移动d个字母即可,也就是删去一个单词,纳入一个单词。
  • 聪明的小伙伴会考虑了,那么万一正确的串被窗口边缘切开了怎么办。
  • 因此,我们需要多走几遍(遍)滑窗,让滑窗起点在[0,1…d-1]的位置分别开始上述步骤。
  • 很明显,这样的话就可以遍历到所有滑窗,不会漏。
  • 滑窗移动时,用一个字典维护窗口中每个单词出现次数,和words相同的话就是满足题意的情况。

2. 复杂度分析

最坏时间复杂度O(n×d),n是s长度,d是word中单词长度

3. 代码实现

滑动窗口

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        wc = Counter(words)
        n = len(s)
        m = len(words)
        d = len(words[0])
        if n < d*m:
            return []
        ans = []
        for start in range(d):
            cnt = Counter()
            i=j = start
            while j < d*m:
                cnt[s[j:j+d]] += 1
                j += d
            if cnt == wc:
                ans.append(start)
            for j in range(j,n,d):
                if j+d>n:
                    break
                cnt[s[j:j+d]] += 1
                l = s[i:j-d*m+d]
                cnt[l] -= 1
                if cnt[l] == 0:
                    del cnt[l]
                # print(j,cnt)

                i += d
                if cnt == wc:
                    ans.append(i)
        return ans

三、 本题小结

  1. 滑窗的灵活运用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值