zoukankan      html  css  js  c++  java
  • bzoj 3172 AC自动机

          初学AC自动机,要先对于每一个模式串求出来trie树,在此基础上构建fail指针,然后在trie树加上失配边构建出整张trie图。

          AC自动机的原理和KMP差不多,一个节点的fail指针就是指向trie树上一个最长前缀等于这个单词的后缀。

          首先fail[0]=0,然后把0有的每个孩子push进一个队列里(如果直接push(0)的话会出现f[x]=x),然后bfs。

          设一个节点为u,父亲为v,那么如果ch[fail[v]][u是v的哪个孩子]!=0,那么fail[u]就等于它,否则就不停的跳fail直到0或存在这个孩子。

          但我们可以用trie图来优化这个过程,每个节点的每个孩子都不为空,如果原本为空就直接指向上一步用while循环求的那个孩子(具体看代码),于是跳的时候无脑跳一步就行了。

          考虑这道题,一个单词一定为trie上的一个节点,而且它出现在文章中一定是一个前缀的后缀,所以那些fail指针直接或间接指向它的节点一定包含这个前缀,所以用bfs序倒着dp一遍就行了。

       

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #define N 1000005
     7 using namespace std;
     8 int n;
     9 char s[N];
    10 int cnt;
    11 int ch[N][26],f[N],ans[N],sum[N];
    12 int b[N];
    13 void in(int xx)
    14 {
    15     int now=0,l=strlen(s);
    16     for(int i=0;i<l;i++)
    17     {
    18         int x=s[i]-'a';
    19         if(!ch[now][x])ch[now][x]=++cnt;
    20         now=ch[now][x];sum[now]++;
    21     }
    22     b[xx]=now;
    23 }
    24 queue<int>q;int a[N];int tot;
    25 void fail()
    26 {
    27     f[0]=0;
    28     for(int i=0;i<26;i++)
    29     {
    30         int u=ch[0][i];
    31         if(u)q.push(u),a[++tot]=u;
    32     }
    33     while(!q.empty())
    34     {
    35         int tmp=q.front();q.pop();a[++tot]=tmp;
    36         for(int i=0;i<26;i++)
    37         {
    38             int u=ch[tmp][i];
    39             if(!u)
    40             {
    41                 ch[tmp][i]=ch[f[tmp]][i];continue;
    42             }
    43             q.push(u);f[u]=ch[f[tmp]][i];
    44         }
    45     }
    46 }
    47 int main()
    48 {
    49     scanf("%d",&n);
    50     for(int i=1;i<=n;i++)
    51     {
    52         scanf("%s",s);
    53         in(i);
    54     }
    55     fail();
    56     for(int i=tot;i>=1;i--)sum[f[a[i]]]+=sum[a[i]];
    57     for(int i=1;i<=n;i++)
    58     {
    59         printf("%d
    ",sum[b[i]]);
    60      } 
    61     return 0;
    62 }
  • 相关阅读:
    【OpenCv/EmguCv】指针式仪表读数(二)
    合天网安实验室CTF练习赛之RE300
    Codeforces Round #527 -A. Uniform String(思维)
    CodeForces
    CodeForces
    CodeForces
    CodeForces
    CodeForces
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6148273.html
Copyright © 2011-2022 走看看