leetcode30 串聯所有單詞的子串(hard)

題目

給定一個字符串 s 和一些長度相同的單詞 words。找出 s 中恰好可以由 words 中所有單詞串聯形成的子串的起始位置。

注意子串要與 words 中的單詞完全匹配,中間不能有其他字符,但不需要考慮 words 中單詞串聯的順序

示例 1:

輸入:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
輸出:[0,9]
解釋:
從索引 0 和 9 開始的子串分別是 "barfoor" 和 "foobar" 。
輸出的順序不重要, [9,0] 也是有效答案。
示例 2:

輸入:
  s = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
輸出:[]

 

思路

這道題得抓住紅色的關鍵字,假設 words 數組中有n個單詞,每個單詞的長度均爲 len,那麼實際上這道題就讓我們求出所有長度爲 n*len 的子串,使得其剛好是由 words 數組中的所有單詞組成

那麼我們就需要經常判斷s串中長度爲 len 的子串是否是 words 中的單詞,爲了快速的判斷,就要使用哈希表,同時由於 words 數組可能有重複單詞,所以就要用 HashMap 來建立所有的單詞和其出現次數之間的映射,即統計每個單詞出現的次數

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> res;
        if(s.empty() || words.empty()) return res;
        int n = int(s.size()),window = int(words[0].size()),num = int(words.size());
        if(n < window*num) return res;
        // 使用字典記錄words
        unordered_map<string,int> m;
        for(auto word:words) m[word]++;
        // 需要遍歷s中所有長度爲 num*window 的子串,當剩餘子串的長度小於 num*window 時,就不用再判斷了
        for(int i = 0;i <= n-window*num;i++){
            int cnt = 0;
            // 新建一個字典,去記錄每個詞使用次數
            unordered_map<string,int> cur_m;
            for(int j = i;cnt < num;j+=window){
                string str = s.substr(j,window);
                // 在原字典找不到,或者使用超過次數,說明不匹配
                if(m.count(str) and m[str] > cur_m[str]) {cur_m[str]++;cnt++;}
                else break;
            }
            if(cnt == num) res.push_back(i);
        }
        return res;
    }
};

 

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