LeetCode:Substring with Concatenation of All Words (summarize)

來源:互聯網
上載者:User

標籤:class   blog   code   http   tar   com   

題目連結

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).

 

演算法1

暴力解法,從字串s的每個位置都判斷一次(如果從當前位置開始的子串長度小於L中所有單詞長度,不用判斷),從當前位置開始的子串的前段部分能不能由集合L裡面的單詞拼接而成。

從某一個位置 i 判斷時,依次判斷單詞s[i,i+2], s[i+3,i+5], s[i+6, i+8]…是否在集合中,如果單詞在集合中,就從集合中刪除該單詞。

我們用一個hash map來儲存單詞,這樣可以在O(1)時間內判斷單詞是否在集合中

演算法的時間複雜度是O(n*(l*k))n是字串的長度,l是單詞的個數,k是單詞的長度

 

遞迴代碼如下:

class Solution {private:    int wordLen;    public:    vector<int> findSubstring(string S, vector<string> &L) {        unordered_map<string, int>wordTimes;        for(int i = 0; i < L.size(); i++)            if(wordTimes.count(L[i]) == 0)                wordTimes.insert(make_pair(L[i], 1));            else wordTimes[L[i]]++;        wordLen = L[0].size();                vector<int> res;        for(int i = 0; i <= (int)(S.size()-L.size()*wordLen); i++)            if(helper(S, i, wordTimes, L.size()))                res.push_back(i);        return res;    }    //判斷子串s[index...]的前段是否能由L中的單片語合而成    bool helper(string &s, const int index,         unordered_map<string, int>&wordTimes, const int wordNum)    {        if(wordNum == 0)return true;        string firstWord = s.substr(index, wordLen);        unordered_map<string, int>::iterator ite = wordTimes.find(firstWord);        if(ite != wordTimes.end() && ite->second > 0)        {            (ite->second)--;            bool res = helper(s, index+wordLen, wordTimes, wordNum-1);            (ite->second)++;//恢複hash map的狀態            return res;        }        else return false;    }};

 

非遞迴代碼如下:

class Solution {private:    int wordLen;    public:    vector<int> findSubstring(string S, vector<string> &L) {        unordered_map<string, int>wordTimes;        for(int i = 0; i < L.size(); i++)            if(wordTimes.count(L[i]) == 0)                wordTimes.insert(make_pair(L[i], 1));            else wordTimes[L[i]]++;        wordLen = L[0].size();                vector<int> res;        for(int i = 0; i <= (int)(S.size()-L.size()*wordLen); i++)            if(helper(S, i, wordTimes, L.size()))                res.push_back(i);        return res;    }        //判斷子串s[index...]的前段是否能由L中的單片語合而成    bool helper(const string &s, int index,         unordered_map<string, int>wordTimes, int wordNum)    {        for(int i = index; wordNum != 0 && i <= (int)s.size()-wordLen; i+=wordLen)        {            string word = s.substr(i, wordLen);            unordered_map<string, int>::iterator ite = wordTimes.find(word);            if(ite != wordTimes.end() && ite->second > 0)                {ite->second--; wordNum--;}            else return false;        }        if(wordNum == 0)return true;        else return false;    }};

 

OJ遞迴的時間小於非遞迴時間,因為非遞迴的helper函數中,hash map參數是傳值的方式,每次調用都要拷貝一次hash map,遞迴代碼中一直只存在一個hash map對象

演算法2

回想前面的題目:LeetCode:Longest Substring Without Repeating Characters 和 LeetCode:Minimum Window Substring ,都用了一種滑動視窗的方法。這一題也可以利用相同的思想。

比如s = “a1b2c3a1d4”L={“a1”,“b2”,“c3”,“d4”}

視窗最開始為空白,

a1在L中,加入視窗 【a1】b2c3a1d4                            本文地址

b2在L中,加入視窗 【a1b2】c3a1d4

c3在L中,加入視窗 【a1b2c3】a1d4

a1在L中了,但是前面a1已經算了一次,此時只需要把視窗向右移動一個單詞a1【b2c3a1】d4

d4在L中,加入視窗a1【b2c3a1d4】找到了一個匹配

如果把s改為“a1b2c3kka1d4”,那麼在第四步中會碰到單詞kk,kk不在L中,此時視窗起始位置移動到kk後面a1b2c3kk【a1d4

class Solution {public:    vector<int> findSubstring(string S, vector<string> &L) {        unordered_map<string, int>wordTimes;//L中單詞出現的次數        for(int i = 0; i < L.size(); i++)            if(wordTimes.count(L[i]) == 0)                wordTimes.insert(make_pair(L[i], 1));            else wordTimes[L[i]]++;        int wordLen = L[0].size();                vector<int> res;        for(int i = 0; i < wordLen; i++)        {//為了不遺漏從s的每一個位置開始的子串,第一層迴圈為單詞的長度            unordered_map<string, int>wordTimes2;//當前視窗中單詞出現的次數            int winStart = i, cnt = 0;//winStart為視窗起始位置,cnt為當前視窗中的單詞數目            for(int winEnd = i; winEnd <= (int)S.size()-wordLen; winEnd+=wordLen)            {//視窗為[winStart,winEnd)                string word = S.substr(winEnd, wordLen);                if(wordTimes.find(word) != wordTimes.end())                {                    if(wordTimes2.find(word) == wordTimes2.end())                        wordTimes2[word] = 1;                    else wordTimes2[word]++;                                        if(wordTimes2[word] <= wordTimes[word])                        cnt++;                    else                    {//當前的單詞在L中,但是它已經在視窗中出現了相應的次數,不應該加入視窗                     //此時,應該把視窗起始位置想左移動到,該單詞第一次出現的位置的下一個單詞位置                        for(int k = winStart; ; k += wordLen)                        {                            string tmpstr = S.substr(k, wordLen);                            wordTimes2[tmpstr]--;                            if(tmpstr == word)                            {                                winStart = k + wordLen;                                break;                            }                            cnt--;                        }                    }                                        if(cnt == L.size())                        res.push_back(winStart);                }                else                {//發現不在L中的單詞                    winStart = winEnd + wordLen;                    wordTimes2.clear();                    cnt = 0;                }            }        }        return res;    }};

演算法時間複雜度為O(n*k))n是字串的長度,k是單詞的長度

 

【著作權聲明】轉載請註明出處:http://www.cnblogs.com/TenosDoIt/p/3807055.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.