• 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 }
  • 相关阅读:
    WPF动态加载3D 放大-旋转-平移
    WPF窗口继承实现统一风格的自定义窗口
    桌面程序的其他实现方式----使用WPF窗体展现网页
    WPF 中自定义控件及其使用
    flask系列三之Jinja2模板
    Python模块学习
    利用Flask-SQLAlchemy提供的paginate()方法实现博客文章的分页显示
    Python利用flask sqlalchemy实现分页效果
    sqlalchemy和flask-sqlalchemy几种分页操作
    Python SQLAlchemy ORM示例
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6479656.html
Copyright © 2020-2023  润新知