[codeVS1204] 單詞背誦

題目描述

靈夢有n個單詞想要背,但她想經過一篇文章中的一段來記住這些單詞。數組

文章由m個單詞構成,她想在文章中找出連續的一段,其中包含最多的她想要背的單詞(重複的只算一個)。而且在背誦的單詞量儘可能多的狀況下,還要使選出的文章段落儘可能短,這樣她就能夠用盡可能短的時間學習儘量多的單詞了。學習

輸入輸出格式

輸入格式:

第1行一個數n,spa

接下來n行每行是一個長度不超過10的字符串,表示一個要背的單詞。code

接着是一個數m,blog

而後是m行長度不超過10的字符串,每一個表示文章中的一個單詞。字符串

輸出格式:

輸出文件共2行。第1行爲文章中最多包含的要背的單詞數,第2行表示在文章中包含最多要背單詞的最短的連續段的長度。string

輸入輸出樣例

輸入樣例#1: 
3
hot
dog
milk
5
hot
dog
dog
milk
hot
輸出樣例#1: 
3
3

說明

【數據範圍】io

對於30%的數據 n<=50,m<=500;class

對於60%的數據 n<=300,m<=5000;map

對於100%的數據 n<=1000,m<=100000;

思路

Trie離散化一下,而後先統計一下ans1,ans2經過對離散化和的數組尺取法求出。

代碼實現

 1 #include<cstdio>
 2 #include<cstring>
 3 const int maxn=1e3+10;
 4 const int maxm=1e5+10;
 5 inline int min_(int x,int y){return x<y?x:y;}
 6 int n,m,ans,now,top,map,lng=1e9;
 7 int s[maxm],v[maxn]={1};
 8 struct tree{int tn,tp;}t[maxm][30];
 9 char ch[12];
10 void add(int k,int i){
11     if(ch[i]==0) return;
12     int next=ch[i]-'a';
13     if(!t[k][next].tn) t[k][next].tn=++top;
14     add(t[k][next].tn,i+1);
15 }
16 int search(int k,int i){
17     int next=ch[i]-'a';
18     if(ch[i]==0){
19         if(!t[k][0].tp) t[k][0].tp=++map;
20         return t[k][0].tp;
21     }
22     if(!t[k][next].tn) return 0;
23     return search(t[k][next].tn,i+1);
24 }
25 int main(){
26     scanf("%d",&n);
27     for(int i=1;i<=n;i++){
28         scanf("%s",ch);
29         add(0,0);
30     }
31     scanf("%d",&m);
32     for(int i=1;i<=m;i++){
33         scanf("%s",ch);
34         s[i]=search(0,0);
35         if(!v[s[i]]) v[s[i]]++,ans++;
36     }
37     printf("%d\n",ans);
38     memset(v,0,sizeof(v)),v[0]=1;
39     for(int i=1,j=1;i<=m;i++){
40         while(now<ans&&j<=m){
41             if(!v[s[j]]) now++;
42             v[s[j]]++;
43             j++;
44         }
45         if(now==ans) lng=min_(lng,j-i);
46         v[s[i]]--;
47         if(!v[s[i]]) now--;
48     }
49     printf("%d\n",lng);
50     return 0;
51 }
相關文章
相關標籤/搜索