bzoj1212: [HNOI2004]L语言(字典树)

1212: [HNOI2004]L语言

题目:传送门 

 


 

 

题解:

   看完题目之后就觉得可以暴力在字典树上之间询问,一开始还傻了以为用文章来建,肯定用单词啊:

   那么我们可以用一个v数组表示当前字符串1~i的区间能够被覆盖,v[0]就初始化一下

   然后一开始就把位置挪到当前已经处理到的能覆盖的位置x,然后从x+1开始在字典树上跑,跑到一个单词的结尾就更新当前位置的v(即使单词有包含关系也没所谓,只要路过就会更新,找不到了才结束,那肯定跑到最后一个位置最优啊),然后重复操作(换一个单词)

   严重吐槽:说好的是字典,哪来的同样的单词???于是没有听企鹅的话...结果就WA了,膜一发捞niang发现他一开始和我一样傻...吐槽吐槽吐槽!!!

 


 

 

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 struct node
 8 {
 9     int c[27],s;
10     node()
11     {
12         memset(c,-1,sizeof(c));
13         s=0;
14     }
15 }tr[410];int cnt;
16 void bt(char *s,int root)
17 {
18     int x=root,len=strlen(s+1);
19     for(int i=1;i<=len;i++)
20     {
21         int y=s[i]-'a'+1;
22         if(tr[x].c[y]==-1)tr[x].c[y]=++cnt;
23         x=tr[x].c[y];
24     }
25     tr[x].s++;//有同样的单词...所以要++ ORZ
26 }
27 int n,m;
28 char s[55],st[1100000];
29 int v[1100000];
30 int main()
31 {
32     scanf("%d%d",&n,&m);
33     for(int i=1;i<=n;i++)
34     {
35         scanf("%s",s+1);
36         bt(s,0);
37     }
38     for(int i=1;i<=m;i++)
39     {
40         scanf("%s",st+1);int len=strlen(st+1);
41         v[0]=i;int x=0,ans=0;
42         while(x<=len)
43         {
44             while(v[x]!=i)
45             {
46                 x++;
47                 if(x==len+1)break;
48             }
49             int r=0;
50             for(int k=x+1;k<=len;k++)
51             {
52                 int y=st[k]-'a'+1;
53                 if(tr[r].c[y]==-1)break;
54                 else
55                 {
56                     r=tr[r].c[y];
57                     if(tr[r].s>0)v[k]=i;
58                 }
59             }
60             x++;
61         }
62         for(int j=len;j>=1;j--)if(v[j]==i){ans=j;break;}
63         printf("%d\n",ans);
64     }
65     return 0;
66 }

 

posted @ 2018-03-21 11:08  CHerish_OI  阅读(260)  评论(0编辑  收藏  举报