http://codevs.cn/problem/3013/
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
查看运行结果
题目描述 Description
灵梦有n个单词想要背,但她想通过一篇文章中的一段来记住这些单词。
文章由m个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。
输入描述 Input Description
第1行一个数n,
接下来n行每行是一个长度不超过10的字符串,表示一个要背的单词。
接着是一个数m,
然后是m行长度不超过10的字符串,每个表示文章中的一个单词。
输出描述 Output Description
输出文件共2行。第1行为文章中最多包含的要背的单词数,第2行表示在文章中包含最多要背单词的最短的连续段的长度。
样例输入 Sample Input
3
hot
dog
milk
5
hot
dog
dog
milk
hot
样例输出 Sample Output
3
3
数据范围及提示 Data Size & Hint
对于30%的数据 n<=50,m<=500;
对于60%的数据 n<=300,m<=5000;
对于100%的数据 n<=1000,m<=100000;
第一问:用Hash得到需要的单词在文章中出现的情况
第二问:想从文章开始就将单词入队,保证需要背的都在队内,然后开始缩短长度
若队头不是需要单词或者在队内的次数多余1,则将其删除
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 #define p 19 7 #define mod 100007 8 const int N(100000+10); 9 char s1[N][11],s2[N][11]; 10 int ans,n,m,num[N],need[N],vis[N],have[N]; 11 12 int Hash(char a[]) 13 { 14 int ret=0; 15 for(int i=0;i<strlen(a);i++) 16 ret=(ret*p+a[i]-‘a‘)%mod; 17 return ret; 18 } 19 20 int main() 21 { 22 scanf("%d",&n); 23 for(int i=1;i<=n;i++) scanf("%s",s1[i]); 24 scanf("%d",&m); int len=m; 25 for(int i=1;i<=m;i++) 26 scanf("%s",s2[i]),have[Hash(s2[i])]=1; 27 for(int i=1;i<=n;i++) 28 { 29 int ha=Hash(s1[i]); 30 if(have[ha]) ans++,need[ha]=1; 31 } 32 for(int cnt=0,head=1,tail=0;tail<=m;) 33 { 34 int ha=Hash(s2[++tail]); 35 if(need[ha]) 36 { 37 if(!vis[ha]) cnt++; 38 num[ha]++; vis[ha]=1; 39 } 40 if(cnt==ans&&ans) 41 { 42 int x=Hash(s2[head]); 43 for(;head<tail&&(num[x]>1||!need[x]);) 44 { 45 if(need[x]) num[x]--; 46 x=Hash(s2[++head]); 47 } 48 len=min(len,tail-head+1); 49 } 50 } 51 if(!ans) printf("0\n0"); 52 else printf("%d\n%d",ans,len); 53 return 0; 54 }
时间: 2024-12-28 08:30:19