30. Substring with Concatenation of All Words 找出包含所有字典中词的开头

来源:互联网 发布:linux 小数比较大小 编辑:程序博客网 时间:2024/05/01 09:19

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;    }


0 0