• 【leetcode】Substring with Concatenation of All Words (hard) ★


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

    For example, given:
    S: "barfoothefoobarman"
    L: ["foo", "bar"]

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

    我的思路,

    设S的长度为Slen, L的长度为Llen, L中每个单词的长度为Lstrlen

    把L中的单词排序

    首个字符遍历S中的每一个字符

           然后以首字符为起点,获取Llen个Lstrlen长度的单词,把获取的单词排序。

           比较两个排序后的单词是否相同。相同则压入答案,不同则遍历下一个起点。

    时间复杂度为O(Slen*Llen*log(Llen))

    结果超时了。分析一下原因:

    S: "barfoothefoobarman"
    L: ["foo", "bar"]

    在遍历第一个起始点时,我们获取了 bar  foo

    在遍历第4个起始点时,我们获取了  foo the.  但这个foo在遍历第一个起始点时已经遍历过了,故我们做了重复的计算。

    ------------------------------------------------------------------------------------------------------

    下面是大神O(Slen*Lstrlen)的答案

    用hash表cn记录每个单词出现的次数

    对 i = 0 - Lstrlen 遍历

          对 j = i - Slen遍历  ;j+= Lstrlen

                 获取以j为起点的一个单词。

                 if(不存在这个单词)

                            起始位置订到下一个单词起始点,数据清0

                 else if(存在这个单词,并且出现次数小于cn中统计的次数)

                           获取的单词数增加

                 else(存在这个单词,但出现次数大于等于cn中统计的次数)

                           把起始位置重新定位到这个单词第一次出现之后

                 if(获取单词数==L中单词数)

                           压入答案

    class Solution {
    public:
        //超时
        vector<int> findSubstring2(string S, vector<string> &L) {
            vector<int> ans;
            if(L.empty()) //L是空的
            {
                return ans;
            }
            int Llen = L.size();
            int Slen = S.size();
            int Lstrlen = L[0].size();
            
            if(Slen < Lstrlen) //S没有L中的字符串长
            {
                return ans;
            }
    
            sort(L.begin(), L.end());
    
            for(int i = 0; i < Slen - Llen * Lstrlen; i++)//起始位置循环
            {
                bool isOK = true;
                vector<string> cur;
                for(int j = 0; j < Llen; j++)
                {
                    cur.push_back(S.substr(i + j * Lstrlen, Lstrlen));
                }
                sort(cur.begin(), cur.end());
                for(int j = 0; j < Llen; j++)
                {
                    if(cur[j] != L[j])
                    {
                        isOK = false;
                        break;
                    }
                }
                if(isOK)
                {
                    ans.push_back(i);
                    i += Llen * Lstrlen - 1;
                }
            }
            return ans;
        }
    };
    
    //大神可以通过的代码
    class Solution2 {
    private:
    vector<int> res;
    map<string,int> cntL;
    map<string,int> cn;
    int n ;
    public:
    vector<int> findSubstring(string S, vector<string> &L) 
    {   res.clear();
        cntL.clear();
        cn.clear();
    
        n = S.length();
        int e = L.size();
        int t = L[0].length();
        int k = 0;
    
        for(int i = 0; i < e ; i++)
             {   if(cn.count(L[i]) == 0)
                   { cn[L[i]] = 1;
                     k++;
                   }
                 else
                    { cn[L[i]] += 1;
                      k++;
                    }
             }
    
        string tr ,du;
        int r = 0;
        int st = 0;
    
        for(int j = 0 ; j < t ; j++)
        { r = 0; st = j;
          for(int i = j; i < n; i += t)
            {     tr = S.substr(i,t);
                  if( cn.count(tr) == 0 || cn[tr] == 0 )
                  { cntL.clear();
                    r =  0;
                    st = i+t;
                  }
                  else if(cntL[tr] < cn[tr])
                  { cntL[tr] += 1;
                    r++;
                  }
                  else
                  {  du = S.substr(st,t);
                     while(du != tr)
                     {   cntL[du]--;
                         r--;
                         st += t;
                         du = S.substr(st,t);
                     }
                     st += t;
                  }
                 if(r == k)
                  {   res.push_back(st);
                      du = S.substr(st,t);
                      cntL[du]--;
                      r--;
                      st += t;
                  }
    
             }
             cntL.clear();
          }
        sort(res.begin(),res.end());
        return res ;    
     }
    };

                  

  • 相关阅读:
    JS浅拷贝和深拷贝
    使用阿里云短信服务
    autojs相关的文档地址记录和简单使用
    Linux 根目录所在分区被脏数据占满
    openstack宿主机故障,虚拟实例恢复
    openstack创建vlan网络并配置网络设备
    联想 lenove 3750 M4服务器更改启动项和管理口IP
    ansible常用方法
    Mysql数据库-多实例主从复制-主从故障详解
    Linux 系统优化-workstation实践
  • 原文地址:https://www.cnblogs.com/dplearning/p/4134748.html
Copyright © 2020-2023  润新知