bzoj 1212: [HNOI2004]L语言 AC自动机+状压

  为什么这道题网上所有题解写的都是N*Len的trie树的暴力啊,4E的复杂度。。。

  为什么暴力还跑这么快啊TAT。。

  有一个O(Len)的做法就是先把AC自动机建出来,因为每个字典串的长度很小,所以我们可以用fail树状压一发,每个节点记录一个值ss,表示这个点向前(1~10)的长度的串是不是一个字典串,这个东西延fail树递推就行了。

  然后每次把每个串放AC自动机上走,同时记录一个值T表示(s(1,i-11)~s(1-(i-1)))这些串能否成为答案,如果如果T&ss!=0那么i这个点就可以成为答案。

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 int n,m;
 8 char s[1500000];
 9 int ch[1005][26];int cnt;int v[10005];
10 int fail[1005];int len[1005];
11 void insert()
12 {
13     int ln=strlen(s);int now=0;
14     for(int i=0;i<ln;i++)
15     {
16         int c=s[i]-'a';
17         if(ch[now][c])
18         {
19             now=ch[now][c];
20         }
21         else
22         {
23             ch[now][c]=++cnt;
24             len[cnt]=len[now]+1;
25             now=ch[now][c];
26         }
27     }
28     v[now]=1;
29 }
30 queue<int>q;
31 unsigned int ss[1005];
32 void build()
33 {
34     for(int i=0;i<26;i++)if(ch[0][i])q.push(ch[0][i]);
35     while(!q.empty())
36     {
37         int tmp=q.front();q.pop();
38         for(int i=0;i<26;i++)
39         {
40             if(ch[tmp][i])
41             {
42                  q.push(ch[tmp][i]);
43                  fail[ch[tmp][i]]=ch[fail[tmp]][i];
44             }
45             else
46             {
47                 ch[tmp][i]=ch[fail[tmp]][i];
48             }
49         }
50         if(v[tmp])ss[tmp]=(ss[fail[tmp]]^(1<<(len[tmp]-1)));
51         else ss[tmp]=ss[fail[tmp]];
52     }
53     return ;
54 }
55 unsigned int tmp;
56 void solve()
57 {
58     int ans=0;
59     unsigned int ssr=1;
60     int ln=strlen(s+1);
61     int now=0;
62     for(int i=1;i<=ln;i++)
63     {
64         int c=s[i]-'a';
65         now=ch[now][c];
66         tmp=ssr;
67         ssr<<=1;
68         if(tmp&ss[now])ans=max(ans,i),ssr^=1;
69     }
70     printf("%d\n",ans);
71     return ;
72 }
73 int main()
74 {
75     scanf("%d%d",&n,&m);
76     for(int i=1;i<=n;i++)
77     {
78         scanf("%s",s);
79         insert();
80     }
81     build();
82     for(int i=1;i<=m;i++)
83     {
84         scanf("%s",s+1);
85         solve();
86     }
87     return 0;
88 }

 

posted @ 2017-02-28 16:55  SD_le  阅读(1298)  评论(0编辑  收藏  举报
重置按钮