单词背诵

问题描述

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

 

正确代码(内存操作错误  改正后)

/*问题描述

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

#include<string> using namespace std;

const int maxn=1e3+5;

const int maxm=1e5+5;

const int maxlen=20;

const int N=10000003;

int n,m,pre[maxm],first[N+5],next[maxn],ans=0,cnt[maxn];

bool visit[maxn];

string a[maxn];

string b[maxm];

inline int hash(string ch){     int ans=0;     int len=ch.size();     for(int i=0;i<len;++i){         ans=(ans*31+ch[i]-'a')%N;     }     return ans%N; }

inline bool same(string a,string b){     int la=a.size();     int lb=b.size();     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(string 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(string 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);    

for(register int i=1;i<=n;i++)

{     cin>>a[i];     add(a[i],i);     }    

scanf("%d",&m);    

for(register int i=1;i<=m;i++)    

{     cin>>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;

}

 

posted @ 2019-03-26 00:05  Tj1  阅读(252)  评论(0编辑  收藏  举报