题意:
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.
s: “barfoothefoobarman”
words: [“foo”, “bar”]
You should return the indices: [0,9]. (order does not matter).
words里面是可能重复的。
初始做法,使用多重映射multimap,很朴素的做法,超时:
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> vec;
if(words.empty()) return vec;
int num = words.size();
int len = words[0].size();
multimap<string, int> mp;
for(int i = 0; i < words.size(); ++i) mp.insert(pair<string, int>(words[i], i));
for(int i = 0; i < s.size() - num * len + 1; ++i){
string str = s.substr(i, num * len);
int k[num];
memset(k, 0, sizeof(k));
for(int j = 0; j < str.size(); j += len){
string tmp = str.substr(j, len);
if(mp.find(tmp) != mp.end()){
pair <multimap<string,int>::iterator, multimap<string,int>::iterator> ret;
ret = mp.equal_range(tmp);
bool ok = false;
for (multimap<string,int>::iterator it=ret.first; it!=ret.second; ++it){
if(k[it->second] == 0){
if(j == str.size() - len) vec.push_back(i);
k[it->second] = 1;
ok = true;
break;
}
}
if(!ok) break;
}
else break;
}
}
return vec;
}
};
后来,改用unordered_map,使用1个映射记录words每个单词的数量,再使用一个映射记录字符串里各单词出现次数,如果出现次数大于对应单词数量,则说明不匹配。
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> vec;
if(words.empty()) return vec;
int num = words.size();
int len = words[0].size();
unordered_map<string, int> mp;
for(string word : words)
mp[word]++;
for(int i = 0; i < s.size() - num * len + 1; ++i){
string str = s.substr(i, num * len);
unordered_map<string, int> mp2;
for(int j = 0; j < str.size(); j += len){
string word = str.substr(j, len);
if(mp.find(word) != mp.end()){
mp2[word]++;
if(mp2[word] > mp[word]) break;
}
else break;
if(j == str.size() - len) vec.push_back(i);
}
}
return vec;
}
};