问题描述
灵梦有n个单词想要背,但她想通过一篇文章中的一段来记住这些单词。
文章由m个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。
输入格式
第1行一个数n,接下来n行每行是一个长度不超过10的字符串,表示一个要背的单词。
接着是一个数m,然后是m行长度不超过10的字符串,每个表示文章中的一个单词。
输出格式
输出文件共2行。第1行为文章中最多包含的要背的单词数,第2行表示在文章中包含最多要背单词的最短的连续段的长度。
输入样例
3 hot dog milk 5 hot dog dog milk hot
输出样例
3 3
HINT
对于30%的数据 n<=50,m<=500;
对于60%的数据 n<=300,m<=5000;
对于100%的数据 n<=1000,m<=100000;
时间限制:1s
空间限制:128MB
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>
using namespace std;
typedef unsigned long long uLL;
map<uLL,int>vis,Map;
map<int,uLL>b;
char a[12];
int gethash(string s)
{
int len=s.length();
uLL sum(0);
for(int i=0;i<len;i++)
sum=sum*131+s[i]-'a';
return sum;
}
int main()
{
// freopen("p386.in","r",stdin);
// freopen("p386.out","w",stdout);
int n,m,sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%s",a);
Map[gethash(a)]=1;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",a);
b[i]=gethash(a);
if( Map[b[i]] && !vis[b[i]] )
{
sum++;
vis[b[i]]=1;
}
}
printf("%d\n",sum);
vis.clear();
int l=0,r=1,ans(1<<30),sumx=0;
while(r<=m)
{
while(r<=m)
{
if(!vis[b[r]] && Map[b[r]] ) sumx++;
vis[b[r]]++;
r++;
if(sumx==sum) break;
}
while(l<r && ( !Map[b[l]] || vis[b[l]]>1 ))
{
vis[ b[l] ]--;
l++;
}
ans = min(ans,r-l);
}
printf("%d",ans);
return 0;
}
来源:https://www.cnblogs.com/hfang/p/11240072.html