30. 串联所有单词的子串

串联所有单词的子串

题目描述:

给定一个字符串 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] 由小写英文字母组成
通过次数115,443提交次数305,855

思路:

时间复杂度:O(ls*n),空间复杂度O(m*n)

用滑动窗口法,把每一个单词当成一个字母做

代码:

func findSubstring(s string, words []string) []int {
    ls,m,n := len(s),len(words), len(words[0])
    var res []int
    for i:=0;i<n&& i<= ls- m*n;i++{
        mp := make(map[string]int, 0)
        for j:=0; j<m; j++{
            mp[s[i+j*n:i+(j+1)*n]]++
        }
        for _,v := range words{
            mp[v]--
            if mp[v] == 0{
                delete(mp,v)
            }
        }
        for start:=i; start< ls - m*n+1; start+=n{
            if start != i{
                mp[s[start-n:start]]--
                if mp[s[start-n:start]] == 0{
                    delete(mp,s[start-n:start])
                }
                mp[s[start+m*n-n:start+m*n]]++
                if mp[s[start+m*n-n:start+m*n]] == 0{
                    delete(mp,s[start+m*n-n:start+m*n])
                }
            }
            if len(mp) == 0{
                res = append(res, start)
            }
        }
    }
    return res
}

代码效率:

执行用时:12 ms, 在所有 Go 提交中击败了72.86%的用户
内存消耗:6.5 MB, 在所有 Go 提交中击败了42.65%


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!