【bzoj3940】[Usaco2015 Feb]Censoring AC自动机

同3942,把KMP换成AC自动机。

开一个栈,记录一下每个位置匹配到哪个节点,如果是单词节点,那么弹出对应长度的字符串。


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 110010 
 
using namespace std;
 
int ch[maxn][26],fail[maxn],q[maxn],w[maxn],dep[maxn];
char s[maxn],st[maxn],s1[maxn];
int n,m,tot,top,root;
 
int newnode()
{
    tot++;
    for (int i=0;i<26;i++) ch[tot][i]=-1;
    return tot;
}
 
void insert()
{
    int n=strlen(s1+1),x=root;
    for (int i=1;i<=n;i++)
    {
        if (ch[x][s1[i]-'a']==-1) ch[x][s1[i]-'a']=newnode();
        x=ch[x][s1[i]-'a']; 
    }
    dep[x]=n;
}
 
void build_fail()
{
    int l=0,r=0;
    fail[root]=root;    
    for (int i=0;i<26;i++)
      if (ch[root][i]==-1) ch[root][i]=root;
      else
      {
        fail[ch[root][i]]=root;
        q[++r]=ch[root][i];
      }
    while (l<r)
    {
        int x=q[++l];
        for (int i=0;i<26;i++)
          if (ch[x][i]==-1) ch[x][i]=ch[fail[x]][i];
          else
          {
            fail[ch[x][i]]=ch[fail[x]][i];
            q[++r]=ch[x][i];
          }
    }
}
 
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    scanf("%s",s+1);
    tot=0;root=newnode();
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",s1+1);
        insert();
    }
    build_fail();
    int x=root,len=strlen(s+1);w[0]=root;
    for (int i=1;i<=len;i++)
    {
        st[++top]=s[i];
        x=ch[x][s[i]-'a'];w[top]=x;
        if (dep[x]) top-=dep[x],x=w[top];
    }
    for (int i=1;i<=top;i++) printf("%c",st[i]);printf("\n");
    return 0;
}


你可能感兴趣的:(【bzoj3940】[Usaco2015 Feb]Censoring AC自动机)