zoukankan      html  css  js  c++  java
  • 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;
    
        }
    };
  • 相关阅读:
    去掉ASP.NET Development Server 中的虚拟路径
    实战 SQL Server 2008 数据库误删除数据的恢复
    人的一生,到底在追求什么?
    每日一记20211215
    CentOS系统配置本地yum源
    mysql修改和查看时区
    依赖报错问题
    没想到MarkText竟然是一款比Typora更简洁优雅的markdown编辑器,完全开源免费!
    免费javascript富文本编辑器 总有一款会适合你!
    90%的人都不知道网页文字被禁止如何复制,教你几招神奇技能就可以免费解决,一定要看完!
  • 原文地址:https://www.cnblogs.com/bbbbbq/p/7622230.html
Copyright © 2011-2022 走看看