codevs3013单词背诵

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

题目大意

灵梦有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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值