zoukankan      html  css  js  c++  java
  • 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
    ",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 }
  • 相关阅读:
    guake 3.4发布,支持切分窗口
    tmux下vim颜色不正常问题
    tmux下make menuconfig背景色不正常问题
    命令行工具PathMarker
    busybox syslog介绍
    linux下检测可用串口并使用minicom打开(改进版)
    linux下检测可用串口并使用minicom打开
    guake终端复制标签页
    shell命令行混合进制计算器smartbc
    在shell脚本中添加暂停,按任意键继续
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6479656.html
Copyright © 2011-2022 走看看