LeetCode | 30. Substring with Concatenation of All Words字符串技巧难题

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;
}
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值