问题描述
灵梦有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
时间: 2024-10-11 07:49:00