Leetcode | Substring with Concatenation of All Words
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).
这题真是自作孽不可活啊。一直想用动态规划去做,但是一旦L里面有重复词就很麻烦。花了几个小时还是没做出来啊。。。我可怜的周末。
网上一看,原来就是扫描每一个位置,从该位置开始对每个单词计数。map里面存的是每个单词出现的次数(可能大于1)。
注意点:
1. S.length()返回值是size_t,如果直接用S.length()-int的话,负数会被转成很大的数;所以以后记得取字符串大小时,用一个int先来存。(Line 9);
2. 用一个map统计word list中每个单词出现的次数; (Line 10-13)
3. 从第i个位置开始,用一个map来统计每个单词出现的次数,该次数不能超过第2步得到的次数;(Line 19);
4. 如果最终合法的单词总数等于L.size()的话,把i存到结果中;(Line 25)。
5. Line 14 不减去wholeLen会出现TLE.
1 class Solution { 2 public: 3 vector<int> findSubstring(string S, vector<string> &L) { 4 vector<int> ret; 5 if (S.empty()) return ret; 6 if (L.empty()) return ret; 7 int len = L[0].size(); 8 int wholeLen = len * L.size(); 9 int n = S.length(); 10 map<string, int> wordCount; 11 for (int j = 0; j < L.size(); ++j) { 12 wordCount[L[j]]++; 13 } 14 for (int i = 0; i <= n - wholeLen; ++i) { 15 string tmp = S.substr(i, len); 16 int pos = i; 17 int c = 0; 18 map<string, int> exist; 19 while (wordCount.count(tmp) > 0 && exist[tmp] < wordCount[tmp]) { 20 c++; 21 pos += len; 22 exist[tmp]++; 23 tmp = S.substr(pos, len); 24 } 25 if (c == L.size()) ret.push_back(i); 26 } 27 return ret; 28 } 29 };
事实上用dfs应该也可以,原理上是一样的,而且后面的不够长的位置就不用检查了。但是会出现MLE.
第三次写简洁许多。一次过。
1 class Solution { 2 public: 3 vector<int> findSubstring(string S, vector<string> &L) { 4 vector<int> ans; 5 if (L.empty() || S.empty()) return ans; 6 unordered_map<string, int> counts, appeared; 7 for (auto str : L) { 8 counts[str]++; 9 } 10 int len = L[0].length(), whole = len * L.size(), n = S.length(); 11 for (int start = 0; start + whole <= n; start++) { 12 appeared.clear(); 13 bool found = true; 14 for (int i = 0; i < whole && start + i < n; i += len) { 15 string tmp = S.substr(start + i, len); 16 appeared[tmp]++; 17 if (counts.count(tmp) < 0 || appeared[tmp] > counts[tmp]) { 18 found = false; 19 break; 20 } 21 } 22 if (found) ans.push_back(start); 23 } 24 25 return ans; 26 } 27 };