P1381

单词背诵

题目描述

灵梦有 \(n\) 个单词想要背,但她想通过一篇文章中的一段来记住这些单词。

文章由 \(m\) 个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。

输入格式

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

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

输出格式

输出文件共 \(2\) 行。第 \(1\) 行为文章中最多包含的要背的单词数,第 \(2\) 行表示在文章中包含最多要背单词的最短的连续段的长度。

样例 #1

样例输入 #1

3
hot
dog
milk
5
hot
dog
dog
milk
hot

样例输出 #1

3
3

提示

数据规模与约定

对于 \(30\%\) 的数据,\(n \le 50\)\(m \le 500\)
对于 \(60\%\) 的数据,\(n \le 300\)\(m \le 5000\)
对于 \(100\%\) 的数据,\(n \le 1000\)\(m \le 10^5\)

双指针好题
点击查看代码
#include<bits/stdc++.h>
using namespace std;
map<string,int>ma;
map<string,int>cs;
string s[100005];
int main()
{
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		string s;
		cin>>s;
		ma[s]=1;
	}
	int m;
	cin>>m;
	int ans1=0,ans2=1e5+5,l=1;
	for(int i=1;i<=m;i++)
	{
		cin>>s[i];
		if(ma[s[i]])cs[s[i]]++;
		if(cs[s[i]]==1)
		{
			ans1++;
			ans2=i-l+1;
		}
		while(l<=i)
		{
			if(!ma[s[l]])
			{
				l++;
				continue;
			}
			if(cs[s[l]]>1)
			{
				cs[s[l]]--;
				l++;
				continue;
			}
			break;
		}
		ans2=min(ans2,i-l+1);
	}
	cout<<ans1<<"\n"<<ans2<<"\n";
	return 0;
}
有个问题 感觉二分也能做但是为什么只有30pts?
posted @ 2023-01-11 13:29  PKU_IMCOMING  阅读(16)  评论(0)    收藏  举报