CODEVS3013 单词背诵 【Hash】【MAP】

CODEVS3013 单词背诵


题目描述 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;


用map水一水hash,双指针记录一下就好了,特判一下结果为0的情况


#include<bits/stdc++.h>
using namespace std;
#define N 100010
map<string,int> mp;
string s;
int t[N],a[N],vis[N],vis1[N]={0};
int n,m,ans1=0,ans2=N;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        cin>>s;
        mp[s]=i;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        cin>>s;
        if(mp.count(s)){
            t[i]=mp[s];
            vis[t[i]]=1;
        }else t[i]=0;
    }
    for(int i=1;i<=n;i++)ans1+=vis[i];
    if(ans1==0){
        printf("0\n0");
        return 0;
    }
    printf("%d\n",ans1);
    int l=1,r=0,count=0;
    while(1){
        while(!t[++r]&&r<=m);
        if(r>m)break;
        if(!vis1[t[r]])count++;
        vis1[t[r]]++;
        while(l<r&&(!t[l]||vis1[t[l]]>1)){
            if(!t[l]){l++;continue;}
            vis1[t[l]]--;
            l++;
        }
        if(count==ans1)ans2=min(ans2,r-l+1);
    }
    printf("%d",ans2);
    return 0;
}
posted @ 2018-06-21 11:39  Dream_maker_yk  阅读(215)  评论(0编辑  收藏  举报