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"]
输出:[]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

//map 和滑动窗口
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if(!s.length()||!words.size())return {};
        int one_size=words[0].length();//一个单词的大小
        int words_size=words.size();//一共又多少个单词
        int size=one_size*words_size;//需要在s中截取的大小
        if(size>s.length())return {};//
        vector<int> res;
        unordered_map<string,int> target;
        for(auto str:words)target[str]++;//设置目标map
        for(int i=0;i<s.length()-size+1;i++)
        {
            unordered_map<string,int> cur;//当前的map
            for(int k=0;k<words_size;k++)//对当前s中截取的字符串 中的words_size个单词进行map统计
            {
                string w=s.substr(i+one_size*k,one_size);//截取一个单词
                if(target.find(w)==target.end())break;//若这个单词在target中没有就结束
                cur[w]++;//统计当前的map
            }
            if(cur==target)res.push_back(i);//若当前的map等于target的map 将i加入到答案中
        }
        return res;
    }
};
//比较map是否相同
//起始位置从0->one_size
//然后一次截取one_size个字符串 设置left和right 
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if(!s.length()||!words.size())return {};
        int one_size=words[0].length();//一个单词的大小
        int words_size=words.size();//一共又多少个单词
        int size=one_size*words_size;//需要在s中截取的大小
        if(size>s.length())return {};
        vector<int> res;
        unordered_map<string,int> target;
        for(const auto& str:words)target[str]++;//设置目标map
        for(int start=0;start<one_size;start++)//设置不同的起点 
        {
            int left=start,right=start,count=0;
            unordered_map<string,int> cur;//当前的map
            while(right+one_size<=s.length())
            {
                string w=s.substr(right,one_size);//截取一个单词
                right+=one_size;//移动右边界
                if(target.find(w)==target.end())//若当前单词不在target中 则重置
                {
                    count=0;
                    cur.clear();
                    left=right;
                }
                else
                {
                    cur[w]++;
                    count++;
                    //为什么是while呢
                    //因为左边第一个单词不一定是w
                    while(target[w]<cur[w])//若当前w的次数大于target中w的次数 则左移
                    {
                        string str=s.substr(left,one_size);
                        cur[str]--;
                        left+=one_size;
                        count--;
                    }
                    if(count==words_size)res.push_back(left);
                }
            }
        }
        return res;
    }
};

 

posted @ 2020-08-10 10:10  lancelee98  阅读(174)  评论(0编辑  收藏  举报