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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words

题目描述

给定一个字符串 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] 由小写英文字母组成

解题思路

题目中重点强调了长度相同,这就是解题的关键,由于长度相同,我们完全可以知道子串的长度就是单个单词长度乘以单词个数,所以可以使用一个子串长度的滑动窗口,依次判断各个起始位置的滑动窗口内子串是否符合题目要求。

同样由于单词长度固定已知,可以直接将窗口内的子串拆解成一个一个单词判断是否在words数组内,为了提高速度,可以把words数组内的单词存入一个哈希表。

代码展示

复制代码
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> viRet;
        unordered_map<string, int> striMap, strimapTemp;
        for(auto word: words)
        {
            striMap[word]++;
        }
        int iLen = words.size() * words[0].size();
        for(int i = 0; i < s.size() - iLen + 1; i++)
        {
            strimapTemp = striMap;
            bool bTemp = true;
            for(int j = 0; j < words.size(); j++)
            {
                string word = s.substr(i + j * words[0].size(), words[0].size());
                if(strimapTemp[word] == 0)
                {
                    bTemp = false;
                    break;
                }
                strimapTemp[word]--;
            }
            if(bTemp)
                viRet.push_back(i);
        }
        return viRet;
    }
};
复制代码

 

运行结果

 

posted @   过客匆匆,沉沉浮浮  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示