我們可以把每個 index 當作可能的起點,然後從這個起點一直往後抓 word 長度的 token 來比較,如果發現已經不在 words 裡了,那就從下一個起點 index 重新開始找,可惜這麼做會 TLE,不過還是記一下 code。
classSolution {public:vector<int> findSubstring(string s,vector<string>& words) { vector<int> res;if(s.empty() ||words.empty()) return res;int idx =0, win_sz =words[0].size();while(idx <s.length()) { // Prepare a set for checking unordered_map<string,int> table;for(auto w: words) { if(table.find(w) !=table.end())table[w] +=1;elsetable[w] =1; } // Start checking from idxint k, l;for(k=0, l=idx; k<words.size(); k++, l+=win_sz) { string tok =s.substr(l, win_sz);if(table.find(tok) !=table.end()) {table[tok]--; }elsebreak; } // Determine if idx is a valid ans positionbool pushFlag =true;for ( auto it =table.begin(); it !=table.end(); ++it )if(it->second !=0) pushFlag =false;if(pushFlag)res.push_back(idx); // Increment idx idx ++; }return res; }};// every time check a window, if consecutive windows contain each
解法二 - 用兩個 Hash table 優化解決過程
解法一裡面有兩個效率很低的地方:
每檢查一個新的 idx,就得重新建立一次 table
為了確認 idx 是否 valid,得 go through 一次 table 看是否所有 value 都是 0
我們可以用兩個 Hash Table,減少解法一裡面的冗餘計算:
classSolution {public:vector<int> findSubstring(string s,vector<string>& words) { vector<int> indexes;if(s.empty() ||words.empty()) return indexes; // Use counts to record the expected times of each word unordered_map<string,int> counts;for (string word : words)counts[word]++; int n =s.length(), num =words.size(), len =words[0].length(); // we check for every possible position of i. // Once we meet an unexpected word // or the times of some word is larger than its expected times, // we stop the check. // If we finish the check successfully, push i to the result indexes.for (int i =0; i < n - num * len +1; i++) { // Use seen to record the times we have seen 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; }elsebreak; }if (j == num) indexes.push_back(i); }return indexes; }};