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 }