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).
利用滚动Hash,接合窗口移动,完成下面这个算法。
思想是,先计算出Hash值,用Hash值完成在map中的查找,最后用字符串精确匹配最验证。
并尽可能推迟并省掉字符串精确匹配。
这个算法虽然被leetcode AC了。 但是实际运行时间并预想的慢多了,高达1272ms。
class Solution {
public:
vector<int> findSubstring(string S, vector<string> &L) {
vector<int> result;
if (L.empty()) return result;
const int itemSize = L[0].size();
const int wndSize = itemSize * L.size();
const int q = 3355439;
const int r = 256;
map<int, vector<int> > map1;
for (int i=0; i<L.size(); i++) {
int nHash = 0;
for (int j=0; j<L[i].size(); j++) {
nHash = ((nHash * r) % q + L[i][j]) % q;
}
map1[nHash].push_back(i);
}
vector<int> total(itemSize);
vector<int> revMap(wndSize);
vector<pair<int,bool> > map2(wndSize);
int head2 = 0;
int weight = 1;
for (int i=1; i<itemSize; i++)
weight = (weight * r) % q;
int nHash = 0;
for (int i=0; i<itemSize-1; i++)
nHash = ((nHash * r) % q + S[i]) % q;
for (int i=itemSize-1; i<S.size(); i++) {
const int group = i % itemSize;
const int offset = group * L.size();
if (map2[head2].first) {
revMap[offset + map2[head2].first - 1] = 0;
map2[head2].first = 0;
map2[head2].second = false;
--total[group];
}
nHash = ((nHash * r) % q + S[i]) % q;
map<int, vector<int> >::iterator iter = map1.find(nHash);
if (iter != map1.end()) {
int pos = -1;
bool compare = true;
const vector<int> &val = (*iter).second;
if (val.size() == 1) {
const int entry = revMap[offset + val[0]];
if (!entry ||
!S.compare(i-itemSize+1, itemSize, L[val[0]])) {
pos = 0;
compare = !!entry;
}
}
else {
compare = true;
int min = i+1;
for (int j=0; j<val.size(); j++) {
if (!S.compare(i-itemSize+1, itemSize, L[val[j]])) {
const int entry = revMap[offset + val[j]];
if (!entry) {
pos = j;
break;
}
else if (entry < min) {
min = entry;
pos = j;
}
}
}
}
if (pos != -1) {
const int entry = revMap[offset + val[pos]];
revMap[offset + val[pos]] = i + 1;
map2[head2].first = val[pos] + 1;
map2[head2].second= compare;
total[group]++;
if (entry) {
const int entry2 = (head2 - i + entry - 1 + wndSize) % wndSize;
map2[entry2].first = 0;
map2[entry2].second= false;
total[group]--;
}
if (total[group] == L.size()) {
for (int j=0; j<L.size(); j++) {
const int entry2 = (head2 - i + revMap[offset+j] - 1 + wndSize) % wndSize;
if (!map2[entry2].second) {
if (!S.compare(revMap[offset+j]-itemSize, itemSize, L[j])) {
map2[entry2].second = true;
}
else {
revMap[offset+j] = 0;
map2[entry2].first = 0;
map2[entry2].second= false;
total[group]--;
break;
}
}
}
if (total[group] == L.size())
result.push_back(i-wndSize+1);
}
}
}
nHash = ((nHash - (S[i-itemSize+1] * weight) % q) % q + q) % q;
head2 = (head2 + 1) % wndSize;
}
return result;
}
};Substring with Concatenation of All Words -- leetcode
原文地址:http://blog.csdn.net/elton_xiao/article/details/42364383