30. Substring with Concatenation of All Words 找出包含所有字典中詞的開頭

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


1.我的答案

用兩個map, 一個map記錄字典中的詞的個數,另一個記錄字符串中的詞的個數;同時用count記錄字符串處理中遍歷到的詞的個數

一個指針對每個字符當作頭進行遍歷; 另一個指針進行當前頭作爲字符進行處理,每len of word進行切分,判斷當前這個word是不是在字典中,如果在字典中,判斷已經遍歷這個詞的個數,如果小於等於字典中的該詞個數,則將其歸納進來,count--; 若大於,則說明不符合,跳出並且i從下一個開頭重新遍歷;(這裏有更好的處理步驟,見下面的做法);如果這個word不在字典中,則也跳出並且i從下一個開頭重新遍歷。

vector<int> findSubstring(string s, vector<string>& words) {
        int len_w = words.size();
        map<string, int>sets; //記錄字典中的詞的個數
        map<string, int>m; //記錄遍歷的字符串中的詞的個數
        for(int i = 0; i < len_w; i++){
            if(sets.find(words[i]) != sets.end())
                sets[words[i]]++;
            else
                sets[words[i]] = 1;
                    
        }
        int l = words[0].size();
        int len_s = s.size();
        vector<int> res;
        if(len_s < l*len_w)
            return res;
        for(int i = 0; i < len_s;){
            int j = i;
            int count = len_w;
            while( j < len_s){
                string str = s.substr(j, l);
                if(sets.find(str) != sets.end()){
                    if(m.find(str) != m.end()){
                        m[str]++;
                        if(m[str] > sets[str])
                            break;
                        else{
                            --count;
                        }
                    }else{
                        m[str] = 1;
                        count--;
                    }
                    if(count == 0) break;
                    j = j+l;
                }else
                    break;
            }
            m.clear();
            if(count == 0)
                res.push_back(i);
            ++i;
        }
        return res;
    }



1(1)  這個的思路跟我一樣,不過比我簡潔多了


class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<string, int> counts;
        for (string word : words)
            counts[word]++;
        int n = s.length(), num = words.size(), len = words[0].length();
        vector<int> indexes;
        for (int i = 0; i < n - num * len + 1; i++) {
            unordered_map<string, int> seen;
            int j = 0;
            for (; j < num; j++) {
                string word = s.substr(i + j * len, len);
                if (counts.find(word) != counts.end()) {
                    seen[word]++;
                    if (seen[word] > counts[word])
                        break;
                } 
                else break;
            }
            if (j == num) indexes.push_back(i);
        }
        return indexes;
    }
};



2.它這個就是兩個指針前後進行移動  別人的更好的解法

// travel all the words combinations to maintain a window
    // there are wl(word len) times travel
    // each time, n/wl words, mostly 2 times travel for each word
    // one left side of the window, the other right side of the window
    // so, time complexity O(wl * 2 * N/wl) = O(2N)
    vector<int> findSubstring(string S, vector<string> &L) {
        vector<int> ans;
        int n = S.size(), cnt = L.size();
        if (n <= 0 || cnt <= 0) return ans;
        
        // init word occurence
        unordered_map<string, int> dict;
        for (int i = 0; i < cnt; ++i) dict[L[i]]++;
        
        // travel all sub string combinations
        int wl = L[0].size();
        for (int i = 0; i < wl; ++i) {
            int left = i, count = 0;
            unordered_map<string, int> tdict;
            for (int j = i; j <= n - wl; j += wl) {
                string str = S.substr(j, wl);
                // a valid word, accumulate results
                if (dict.count(str)) {
                    tdict[str]++;
                    if (tdict[str] <= dict[str]) 
                        count++;
                    else {
                        // a more word, advance the window left side possiablly
                        while (tdict[str] > dict[str]) {
                            string str1 = S.substr(left, wl);
                            tdict[str1]--;
                            if (tdict[str1] < dict[str1]) count--;
                            left += wl;
                        }
                    }
                    // come to a result
                    if (count == cnt) {
                        ans.push_back(left);
                        // advance one word
                        tdict[S.substr(left, wl)]--;
                        count--;
                        left += wl;
                    }
                }
                // not a valid word, reset all vars
                else {
                    tdict.clear();
                    count = 0;
                    left = j + wl;
                }
            }
        }
        
        return ans;
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章