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中每个字符长度为l,index[i]用来存S中以第i个字符开头且长度为l的字符串是否包含在L中,如果在则为L的值,否则是-1。这里需要注意的是L中的字符串可能会有重复的,所以在遇到index[i]不为-1的情况就不继续往后算。这一步的复杂度是O(mnl)(m为S的长度,n为L中字符串的数量,l为L中每个字符串的长度)。
needNum记录L中每个字符串需要的次数,hasNum记录当前找到的L中字符串的次数。
对S进行一次遍历,如果index[i]等于-1继续往后走,否则的话计算从i开始数n个字符后中hasNum的值。最后比较hasNum和needNum,如果全部相等,则把该结果存入最终vector。
代码:
1 vector<int> findSubstring(string S, vector<string> &L) { 2 int ls = S.length(), n = L.size(); 3 vector<int> result; 4 if(n == 0) 5 return result; 6 int ll = L[0].length(); 7 int index[ls]; 8 memset(index, -1, sizeof(int)*ls); 9 int needNum[n], hasNum[n]; 10 for(int i = 0; i < n; i++) 11 needNum[i] = 1; 12 int i, j, k; 13 const char *s = S.c_str(); 14 for(i = 0; i < n; i++){ 15 const char *l = L[i].c_str(); 16 char *tmp = strstr(s, l); 17 if(tmp != NULL){ 18 if(index[tmp-s] != -1){ 19 needNum[index[tmp-s]]++; 20 needNum[i] = 0; 21 continue; 22 } 23 } 24 while(tmp){ 25 index[tmp-s] = i; 26 tmp = strstr(tmp+1, l); 27 } 28 } 29 for(i = 0; i < ls; i++){ 30 if(index[i] == -1) 31 continue; 32 memset(hasNum, 0, sizeof(int)*n); 33 for(j = i; j < (ls<(i+n*ll)?ls:(i+n*ll)); j+=ll){ 34 if(needNum[index[j]] == hasNum[index[j]]){ 35 break; 36 } 37 hasNum[index[j]]++; 38 } 39 for(k = 0; k < n; k++){ 40 if(needNum[k] != -1 && hasNum[k] != needNum[k]) 41 break; 42 } 43 if(k == n) 44 result.push_back(i); 45 } 46 return result; 47 }
第二遍:
1 vector<int> findSubstring(string S, vector<string> &L) { 2 // Start typing your C/C++ solution below 3 // DO NOT write int main() function 4 map<string, int> words; 5 map<string, int> count; 6 vector<int> result; 7 int wordNum = L.size(); 8 if (wordNum == 0) return result; 9 for (int i = 0; i < wordNum; ++i) 10 ++words[L[i]]; 11 12 int wordSize = L[0].size(); 13 int slength = S.size(); 14 for (int i = 0; i <= slength - wordSize*wordNum; ++i) 15 { 16 count.clear(); 17 int j = 0; 18 for (; j < wordNum; ++j) 19 { 20 string w = S.substr(i+j*wordSize, wordSize); 21 if(words.find(w) == words.end()) 22 break; 23 ++count[w]; 24 if(count[w] > words[w]) 25 break; 26 } 27 if (j == wordNum) result.push_back(i); 28 } 29 return result; 30 }