30. Substring with Concatenation of All Words

Posted =w=

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了30. Substring with Concatenation of All Words相关的知识,希望对你有一定的参考价值。

link

 

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

 

题意:

给定一个字符串s, 和一些【长度相同的字符串】列表V。设V的大小为|V|, V中字符串的长度为wordLen

则对字符串s的某一个位置j,若j为起始位置,长度为|V| * wordLen 子串,是V中的所有元素的某一种拼接结果,则为满足条件。按顺序输出所有满足条件的j

注意: V中的元素会有重复。

 

思路:

最暴力的解法就是枚举每一个位置,查看其后子串是否满足条件。复杂度O(|s| * |V| * wordLen) 不优雅。

分析上面的方法我们可以发现,对于枚举j和j+wordLen位置,中间有一大块运算是重复的。

因此我们维护一个窗口,定义aim<string, int>为一个长度为wordLen的子串的期待的个数。(从V中搞定), now<string, int>为目前所需的该子串的数量, 枚举的单位为长度为wordLen的字符串。 发现首先枚举0, wordLen, 2 * wordLen , .. ; 然后枚举1 , 1 + wordLen, 。。。。; 2 , 2 + wordLen ,。。。; 直至wordLen - 1, wordLen - 1 + wordLen, 。。。, 即可枚举完所有的串。且每一块枚举满足每一个元素为连续且不重叠的长度为wordLen的串。

当右端的加入满足条件(即设右端的子串为y,now[y] > 0), 曾将其加入。可以看到该元素若不加入则左边所有的信息都应清零,且存在左边的某些串就是y,删去它可以使得now[y] > 0 条件成立。因此在此条件不满足时,需要逐个从窗口中删去左边的子串。然后判定是否能加入(now[y] > 0)。

判定成功的条件即为窗口中的元素个数 = |V|。

 

注意事项:

不能在now[y]为0的时候简单判断不能加入,而是要看左边能不能删掉一些使得右边能加入。

若确实不能加入,记得更新left

 

code:

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> res;
        if(words.size() == 0 || s == "") return res;
        unordered_map<string, int> aim;
        for(int i = 0; i < words.size(); i++){
            aim[words[i]] += 1;
        }
        int wordLen = words[0].length();
        int strLen = s.length();
        for(int i = 0; i < wordLen; i++){
            int left = i, cnt = 0;
            unordered_map<string, int> now = aim;
            for(int j = i; j <= strLen - wordLen; j += wordLen){

                string temp = s.substr(j, wordLen);
                /**!! notion: . case like
                "barfoofoobarthefoobarman"
                ["bar","foo","the"] , we can not throw all previous information, but delete some useless information
                **/
                while((now.count(temp) == 0 || (now[temp] == 0)) && left < j){
                    cnt --;
                    now[s.substr(left, wordLen)] ++;
                    left += wordLen;
                }

                if(now.count(temp) == 1 && now[temp] != 0) {
                    now[temp] --;
                    cnt ++;
                    if(cnt == words.size()){
                        res.push_back(left);
                    }
                }else{
                    /**
                    notion : if we do not use this substring, then the left side need to be updated.
                    **/
                    left = j + wordLen;
                }
            }
        }
        sort(res.begin(), res.end());
        return res;

    }
};

 

以上是关于30. Substring with Concatenation of All Words的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 30 Substring with Concatenation of All Words

30. Substring with Concatenation of All Words

30. Substring with Concatenation of All Words

19.1.30 [LeetCode 30] Substring with Concatenation of All Words

30. Substring with Concatenation of All Words

30. Substring with Concatenation of All Words