LeetCode:30. Substring with Concatenation of All Words

这道题并不是很难(虽然没有做出来),让我感到惊讶的是oj竟然接受了一个看上去这么耗时的方法。
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
if (words.empty())
return vector<int>();
unordered_map<string, int> cnts;
for (auto& str : words)
cnts[str]++;
int len = words[0].size(), sz = words.size();
vector<int> ret;
for (int i = 0; i < s.size() - len * sz + 1; ++i) {
unordered_map<string, int> seen;
int k;
for (k = 0; k < sz; ++k) {
string ss = s.substr(i+k*len, len);
if (find(words.begin(), words.end(), ss) != words.end()) {
++seen[ss];
if (seen[ss] > cnts[ss])
break;
} else
break;
}
if (k == sz)
ret.push_back(i);
}
return ret;
}
};
在我眼中,循环每次创造一个map,截取很多子串,然后find,这样都是很耗时的操作,但是没想到竟然就是这么笨的方法过了。
其实来说,这一题看上去,就是一个很耗时的题目,基本上是每个位置都要检查的。所以下次不要觉得自己方法笨就不去试一下了
ok,其实是有优化的方法的。
每次移动一个单词的长度,就可以使用滑动窗口了。
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
unordered_map<string, int> dict;
for (auto& word : words)
dict[word]++;
int sz = words.size();
if (sz == 0)
return vector<int>();
int wordSz = words[0].size();
vector<int> res;
for (int i = 0; i < wordSz; ++i) {
unordered_map<string, int> window;
int cnt = 0;
for (int j = i; j < s.size()-wordSz+1; j += wordSz) {
if (j >= i+wordSz*sz) {
string str = s.substr(j-wordSz*sz, wordSz);
if (dict.find(str) != dict.end()) {
--window[str];
if (window[str] < dict[str])
--cnt;
}
}
string str = s.substr(j, wordSz);
if (dict.find(str) != dict.end()) {
window[str]++;
if (window[str] <= dict[str])
++cnt;
if (cnt == sz)
res.push_back(j - (sz-1)*wordSz);
}
}
}
return res;
}
};
浙公网安备 33010602011771号