bzoj3172: [Tjoi2013]单词(AC自动机)

https://www.lydsy.com/JudgeOnline/problem.php?id=3172

 

构建AC自动机

在fail树上,点i的子树大小 表示trie树上根节点到i构成的单词 是 多少个(子)串的子串

 

#include<queue>
#include<cstdio>
#include<cstring>

using namespace std;

#define N 2000001

using namespace std;

int pos[201];

int tr[N][26],id=1;
int f[N],ans[N];

char s[1000001];

queue<int>q;

int d[N],cnt;

void insert(int &pos)
{
    int now=1,len=strlen(s);
    int x;
    for(int i=0;i<len;++i)
    {
        x=s[i]-'a';
        if(!tr[now][x]) tr[now][x]=++id;
        now=tr[now][x];
        ans[now]++;
    }
    pos=now;
}

void get_fail()
{
    for(int i=0;i<26;++i) tr[0][i]=1;
    q.push(1);
    int now,j;
    while(!q.empty())
    {
        now=q.front();
        d[++cnt]=now;
        q.pop();
        for(int i=0;i<26;++i) 
            if(!tr[now][i]) tr[now][i]=tr[f[now]][i];
            else
            {
                q.push(tr[now][i]);
                j=f[now];
                f[tr[now][i]]=tr[j][i];
            }
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s);
        insert(pos[i]);
    }
    get_fail();
    for(int i=cnt;i;--i) ans[f[d[i]]]+=ans[d[i]];
    for(int i=1;i<=n;++i) printf("%d\n",ans[pos[i]]); 
}
posted @ 2018-05-01 22:10  TRTTG  阅读(265)  评论(0编辑  收藏  举报