codevs3013单词背诵

来源:互联网 发布:我的世界pe枪械js下载 编辑:程序博客网 时间:2024/04/29 20:31

来自我在另一个站点写的博客

题目大意

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

输入格式

第1行一个数n,
接下来n行每行是一个长度不超过10的字符串,表示一个要背的单词。
接着是一个数m,
然后是m行长度不超过10的字符串,每个表示文章中的一个单词。

输出格式

输出文件共2行。第1行为文章中最多包含的要背的单词数,第2行表示在文章中包含最多要背单词的最短的连续段的长度。
样例输入
3
hot
dog
milk
5
hot
dog
dog
milk
hot
样例输出
3
3

思路

map+贪心
有时候,看见这种题目,就觉得map这种东西简直太好了。如果你不知道map是什么的话,推荐一个神犇的博客:http://www.cnblogs.com/rjgcs/p/5721873.html
那么,我们先用map将每一个要背的单词变成一个数字,这样处理起来会方便很多。不要背的单词就是0啦。
我们开始读入文章,我开了一个数组ar,我不会告诉你这是artcle的缩写的,用于记录我们现在“所背的”单词表。jl是用于记录我们背的单词在单词表中最后一次出现的位置,jjl则是记录该单词在文章中的位置。(注意,我说的单词表不是指要背的单词!!!是指ar数组!!!)假如发现文章中有一个要背的单词,我们就把这个单词加入单词表,单词表记录的是这个单词map映射出来的值。
我们读入一个新单词的时候,会出现以下情况:
1.如果这个单词不在所背的单词表里。
那么为了背更多的单词,我们需要把这个单词加入单词表中。更新一下ans1和ans2的值。
2. 如果这个单词在单词表里
没关系,大胆地将单词加入单词表中吧,如果单词表的长度扩展了,你不用更新ans的值。
3.如果此时队首的单词不止一个了,右移队首指针(一定要注意队首单词不是要背的单词的情况)。然后再看ans能否更新
光这么说肯定很多人都听不懂。我们还是例子分析。
就拿样例来说吧。
要背的单词是:hot(1),dog(2),milk(3)。
现在我们读入文章,第一个单词是hot,此时ans1=1,an2=1。
第二个单词是dog,ans1=2,ans2=2。
第三个还是dog,所以不更新ans,只将该单词放入ar中。
第四个是milk,ans1=3,ans2=4。
第五个是hot,将单词放入ar中,那么我们就需要将ar数组首指针head后移一位,指向dog,而队伍中存在其它的dog,所以再后移一位。head=3。

更新得到ans1=3,ans2=3。

代码

#include<algorithm>#include<iostream>#include<cstring>#include<climits>#include<cstdio>#include<map>using namespace std;int n,m,tot,l=1,r=0,ok;map<string,int>ma;string s;int ans1,ans2;int num[1005],t[100005];int main(){    int i,j;    scanf("%d",&n);    for(i=1;i<=n;++i){        cin>>s;        if(!ma[s])ma[s]=++tot;    }    scanf("%d",&m);    for(i=1;i<=m;++i){        cin>>s;        ++r;        if(ma.count(s)){            t[i]=ma[s];            if(!num[t[i]])++ans1,ans2=r-l+1;            ++num[t[i]];        }        while(l<=r&&(num[t[l]]>1||num[t[l]]<=0))--num[t[l]],++l;        ans2=min(ans2,r-l+1);    }    printf("%d\n%d",ans1,ans2);    return 0;}


0 0
原创粉丝点击