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).
首先合并相同项并统计出现次数
之后通过kmp算法实现O(n*l*k) 复杂度的预处理得出主串上每一位能够匹配的子串的序号,其中n为主串长度,l为所有字串个数,k为子串长度
之后通过O(k*(n/k))复杂度的遍历计算从第i个字符开始,每隔K位的情况 i的取值范围为【0-k)
class Solution { public: void BuildKmp(string s,vector<int>& next){ next[0]=-1; next[1]=0; for(int j=2;j<s.length();j++){ int i=next[j-1]; while(i>=0&&s[i]!=s[j-1]){ i=next[i]; } i++; next[j]=i; } } vector<int> findSubstring(string S, vector<string> &L) { // Note: The Solution object is instantiated only once and is reused by each test case. sort(L.begin(),L.end()); vector<string> list; vector<int> count; list.push_back(L[0]); count.push_back(1); for(int i=1;i<L.size();i++){ if(L[i]==L[i-1])count[count.size()-1]++; else{ list.push_back(L[i]); count.push_back(1); } } int len=list[0].length(); if(S.length()<L.size()*len)return vector<int>(); vector<int> next; next.resize(len); vector<int> index; index.resize(S.length(),-1); for(int i=0;i<list.size();i++){ BuildKmp(list[i],next); int p=0; for(int j=0;j<S.length();j++){ if(S[j]==list[i][p]){ p++; if(p==len){ index[j-len+1]=i; p=next[p-1]; while(p>=0&&list[i][p]!=S[j]){ p=next[p]; } p++; } } else{ while(p>=0&&list[i][p]!=S[j]){ p=next[p]; } p++; } } } vector<int> count2; count2.resize(count.size(),0); vector<int>ret; for(int i=0;i<len;i++){ int start=i; int end=start; for(int mm=0;mm<count2.size();mm++)count2[mm]=0; while(true){ if(index[end]==-1){ for(int j=start;j<end;j+=len){ count2[index[j]]=0; } end+=len; if(end>=S.length())break; start=end; } else{ while((count2[index[end]]==count[index[end]])){ count2[index[start]]--; start+=len; } count2[index[end]]++; if(end-start==(L.size()-1)*len){ ret.push_back(start); count2[index[start]]--; start+=len; end+=len; if(end>=S.length())break; } else{ end+=len; if(end>=S.length())break; } } } } return ret; } };