标签:
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.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
给出一个字符串S和一个单词列表,这些单词的长度相同。找到所有的子串的起始位置,子串要包含单词列表里的每个单词,且仅包含一次,单词在子串里不能重叠。
也就是说子串是这些单词的排列组合的一种,如果每个起点都去做检查那么需要比较N*M*K次,N是S的长度,M是单词的长度,K是单词的个数。但是因为单词的长度都是相同的,可以对S进行切分,每M个字符为一段,总共会有M种切分方法,起始切分位置分别为0~M-1。这个将问题等价于:在一个字符串中,求包含某个单词集合的子串。
时间复杂度改进为O(N*M),给出的代码如下:
vector<int> findSubstring(string s, vector<string>& words) { map<string, int> dict; for (int i=0; i<words.size(); ++i) ++dict[words[i]]; vector<int> ret; int m = words.size(); int len = words[0].size(); int n = s.size(); if (0==m) return ret; if (n < m) return ret; for (int i=0; i<len; ++i) { int cnt = 0; map<string, int> curdict; int j=i, k=i; // j是起始位置,k是结束位置 while (k+len<=s.size()) { string str = s.substr(k, len); k += len; if (dict.end() == dict.find(str)) { cnt = 0; curdict.clear(); j = k; } else if (++curdict[str] > dict[str]) { --curdict[str]; while (s.substr(j,len) != str) { --curdict[s.substr(j,len)]; --cnt; j += len; } j += len; } else { ++cnt; if (cnt == m) { ret.push_back(j); --curdict[s.substr(j,len)]; --cnt; j += len; } } } } return ret; }
30. Substring with Concatenation of All Words
标签:
原文地址:http://www.cnblogs.com/zhiguoxu/p/5467963.html