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 wordin words exactly once and without anyintervening characters.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
这一题写的我想打人,从头到尾我理解出了三种不同的意思,然后我就写了三个不同的程序,难怪这一题的差评这么的多
这题需要注意的是题目中有两个陷阱,首先需要注意concatenation的意思,这个单词的意思是级联,而不是包含,因此当你在写程序的时候需要注意,words里面的单词不能够重复包含,要不然会出现错误,words里面的单词需要在子串中首尾相连,在子串中不能重叠,并且每个单词只能出现一次,中间不能有其他额外的字母
还有一个陷阱就是我原来以为each word in words exactly once的意思是就算是重复的字母也只需要出现一次就行了,没想到这一句的意思是当出现多个相同的字母的时候相同的字母出现了的多少次你的结果里面就要出现多少次,这个错误的理解导致我又写了一个错误的代码版本
我的算法的基本思路就是首先遍历words,把这个数组里面出现的每一个单词在原字符串中的位置都标记出来,然后遍历标记之后的数组,使用贪心算法,从每一个有效的字母位置开始遍历mark数组,之间使用了一些技巧排除了肯定不处在解的结果
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
int theAllLetter = words.size();
vector<int> result;
if (words.size() == 0) return result;
int l = words[0].size();
vector<bool> tmpMark(s.size(),false); int tmp;
map<int, int> mark;
vector<int> doesHave(theAllLetter, 0);
vector<int> Ineed(theAllLetter, 0);
list<int> theStore;
for (int i = 0; i < words.size(); i++)
{
tmp = s.find(words[i], 0);
if (tmp == -1) { return result; }
if (tmpMark[tmp])
{
int u = 0;
while (words[u] != words[i]) u++;
Ineed[u]++;
continue;
}
else
{
Ineed[i]=1;
mark[tmp] = i;
tmpMark[tmp] = true;
while (tmp != -1)
{
tmpMark[tmp] = true;
mark[tmp] = i;
tmp = s.find(words[i], tmp + 1);
}
}
}
map<int, int> ::iterator left, right,p;
right=left = mark.begin();
int doesHaveCount = 0;
p = mark.begin();
while (right != mark.end())
{
doesHaveCount++;
doesHave[(*right).second]++;
int u = (*right).first;
int u2 = (*left).first;
theStore.push_back((*right).second);
if (doesHaveCount == theAllLetter)
{
result.push_back((*left).first);
doesHaveCount--;
doesHave[(*left).second]--;
theStore.pop_front();
p = left++;
if ((*left).first - (*p).first == l) goto findTheN;
else
{
while (!theStore.empty())
{
int u = theStore.front();
theStore.pop_front();
doesHaveCount--;
doesHave[u]--;
}
right = left; continue;
}
}
findTheN:;
p = right++;
while (right!=mark.end()&&(*right).first - (*p).first < l)
right++;
if (right == mark.end()) break;
if ((*right).first - (*p).first > l)
{
doesHaveCount--;
doesHave[(*left).second]--;
theStore.pop_front();
p = left++;
while ((*left).first - (*p).first == l) {
doesHaveCount--;
doesHave[(*left).second]--;
theStore.pop_front();
p = left++; }
while (!theStore.empty())
{
int u = theStore.front();
theStore.pop_front();
doesHaveCount--;
doesHave[u]--;
}
right = left;
continue;
}
if (doesHave[(*right).second] >= Ineed[(*right).second])
{
doesHaveCount--;
doesHave[(*left).second]--;
theStore.pop_front();
p = left++;
while ((*left).first - (*p).first == l&&doesHave[(*right).second] >= Ineed[(*right).second]) {
doesHaveCount--;
doesHave[(*left).second]--;
theStore.pop_front();
p = left++;
}
if ((*left).first - (*p).first == l)
{
continue;
}
else
{
while (!theStore.empty())
{
int u = theStore.front();
theStore.pop_front();
doesHaveCount--;
doesHave[u]--;
}
right = left;
continue;
}
}
}
return result;
}
};