单词背诵

/*问题描述

灵梦有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<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
const int maxn=1e3+5;
const int maxm=1e5+5;
const int maxlen=20;
const int N=1000007;
int n,m,pre[maxm],first[N+5],next[maxn],ans=0,cnt[maxn];//cnt[i]琛ㄧず鍗曡瘝i鑳屼簡澶氬皯娆?
bool visit[maxn];
char a[maxn][maxlen],b[maxm][maxlen];
inline int hash(char *ch){
    int ans=0;
    int len=strlen(ch);
    for(int i=0;i<len;++i){
        ans=(ans*31+ch[i]-'a')%N;
    }
    return ans%N;
}
inline bool same(char *a,char *b){
    int la=strlen(a);
    int lb=strlen(b);
    if(la!=lb)return 0;
    for(register int i=0;i<la;++i){
        if(a[i]!=b[i])return 0;
        }    
    return 1;
}
inline void add(char *ch,int pos){
    int key=hash(ch);
    for(int i=first[key];i;i=next[i]){
    if( same( ch , a[i]) )return;
    }
    next[pos]=first[key];
     first[key]=pos;
}
inline void find(char *ch,int pos){
    int key=hash(ch);
    for(register int i=first[key];i;i=next[i]){
        if( same( ch , a[i] ) ){
            pre[pos]=i;
            if(!visit[i])ans++;
            visit[i]=1;
            }
    }
}
int main()
{
    /*freopen("p386p.in","r",stdin);
    freopen("p386p.out","w",stdout);*/
    scanf("%d",&n);
    gets(a[0]);
    for(register int i=1;i<=n;i++){
    gets(a[i]);
    add(a[i],i);
    }
    scanf("%d",&m);
    gets(b[0]);
    for(register int i=1;i<=m;i++)
    {
    gets(b[i]);
    find(b[i],i);
    }
    printf("%d\n",ans);
    int kk=ans;
    ans=0x7fffffff;
    int right=0,left=0,temp=0;
    while(right<=m){
        right++;
        if(!pre[right])continue;
        if(!cnt[ pre[right] ])temp++;
        cnt[ pre[right] ]++;
        while(left<=right && temp==kk){
            ans=min(ans,right-left+1);
            if(cnt[ pre[left] ]==1)temp--;
            cnt[  pre[left] ]--;
            left++;
        }
        
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/a-blog-of-taojiayi-2003/p/10597748.html