3172: [Tjoi2013]单词

来源:互联网 发布:访客网络永远保存密码 编辑:程序博客网 时间:2024/05/17 04:48

题目链接

题目大意:给定一个n个单词的文章,求每个单词在文章中的出现次数

题解:每加入一个串,就给这个串的路径上所有点的sum+1,表示它的前缀都又出现了一次

按照fail树中的bfs序自下而上加起来……

我的收获:AC自动机T1 get

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define idx s[i]-'a'const int M=1000010;int n,w[210];char s[M];struct AC_DFA{    int tot,c[M][26],fail[M],q[M],l,r,sum[M];    void insert(int &x){        int p=0,len=strlen(s);        for(int i=0;i<len;i++){            if(!c[p][idx]) c[p][idx]=++tot;            ++sum[p=c[p][idx]];        }        x=p;    }    void getfail(){        l=0,q[r=1]=0,fail[0]=-1;        while (l!=r){            int x=q[++l];            for(int i=0;i<26;i++){                if(c[x][i]) q[++r]=c[x][i],fail[c[x][i]]=!x?0:c[fail[x]][i];                else c[x][i]=!x?0:c[fail[x]][i];            }        }    }    void work(){        for(int i=r;i;i--) sum[fail[q[i]]]+=sum[q[i]];        for(int i=1;i<=n;i++) printf("%d\n",sum[w[i]]);    }}T;void init(){    scanf("%d",&n);    for(int i=1;i<=n;i++) scanf("%s",s),T.insert(w[i]);    T.getfail(),T.work();}int main(){    init();    return 0;}