Sicily1222——单词选择

1222. 单词选择

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

我们都知道,学习英语单词最好的方法就是在相应的句子和语言环境中去学习它。小W最近定下了一个学习单词的计划,他有n个单词要背,但他想在通过背出一篇文章中的一段来记住这些单词。

假定现在小W手头有一篇包含m个单词的文章,现在他想在文章中找出连续的一段,其中包含最多的他所要背的单词(重复的只算一个),并且使这段连续的单词长度最短。这样他就可以用尽量短的时间学习到尽可能多的单词了。

Input

第一行一个数n1<=n<=1000

接下来n行每行是一个长度不超过10的字符串,表示一个要背的单词。

接着是一个数m1<=m<=100000

然后是m行长度不超过10的字符串,每个表示文章中的一个单词。

Output

两行,第一行为文章中最多包含的要背的单词数,第二行表示在文章中包含最多要背单词的最短的连续段的长度。

Sample Input

3hotdogmilk5hotdogdogmilkhot

Sample Output

33

不得不说,这题是一道经典的动态规划问题。找到文章中有多少单词是要背的单词这个问题很简单,下面解释怎么求解第二个问题。
当遇到一个单词的时候(规划尾指针):
1,这个单词是要背诵的单词,但是我们以前没有遇到,此时将这个单词的遇到的数量加一,并且更新我们的最小长度。
2,其他情况我们完全不必操作,因为只有遇到上述情况的单词才会对我们的结果产生影响。

每次尾指针规划完之后,我们都得规划头指针:
1,这个单词是我们不需要背诵的单词,那么直接丢弃这个单词,即将头指针指向下一个位置。
2,这个单词是要求背诵的单词,但是我们遇到过超过一次了,那么就将这次遇到的丢弃(头指针指向下一个位置)并且将这个单词我们遇到的数量减一。

卡了我很久,希望这样写出来能帮到后来人~

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <map> 

using namespace std;

int main()
{
	int n,m;
	cin >> n;
	
	string str;
	map<string,bool> mp;
	for(int i=0;i<n;i++)
	{
		cin >> str;
		mp[str] = true;
	}
	
	cin >> m;
	string word[100001];
	map<string,int> f;
	int mark1 = 0,mark2 = 0,l,cnt = 0;
	while(mark2<m)
	{
		cin >> word[mark2];
		if(mp[word[mark2]])
		{
			if(f[word[mark2]] == 0)
			{
				cnt++;
				l = mark2-mark1+1;
			}
			f[word[mark2]]++;//这个单词出现的次数加一
		}
		while(mark1 < mark2)
		{
			 //如果这个单词在first到last之间有多个,那么把first的这个删除
			 //把不需要的单词删除
			if(mp[word[mark1]] == true && f[word[mark1]] >1 || mp[word[mark1]] == false)
			{
				f[word[mark1]]--;
				mark1++;
			}
			else break;
		}
		if (mark2 - mark1 + 1 < l) l = mark2 - mark1 + 1;
        mark2++;
	}
	cout << cnt << endl;
	cout << l << endl;
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值