3172: [Tjoi2013]单词

来源:互联网 发布:微软亚洲研究院 知乎 编辑:程序博客网 时间:2024/05/17 01:49

后缀自动机模板题。

2012noi稿(SAM)

这个写的不错,一定要耐心看。
code:
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>using namespace std;struct SAM{    int par,max,a[28];}sam[2500000];int root=1,tot=1,tail=1,ri[2500000];int num=0;char s[1000400],ch[1000010];struct node{    int y,next;}a[2500000];int last[2500000],len=0;void addsam(int c,int len){    int p=tail,np=++tot;    sam[np].max=len;ri[np]=1;    for(;p&&!sam[p].a[c];p=sam[p].par) sam[p].a[c]=np;    tail=np;    if(!p) sam[np].par=root;    else    {        int q=sam[p].a[c];        if(sam[q].max==sam[p].max+1) sam[np].par=q;        else        {            int nq=++tot;sam[nq]=sam[q];            sam[nq].max=sam[p].max+1;            sam[q].par=sam[np].par=nq;            for(;p&&sam[p].a[c]==q;p=sam[p].par) sam[p].a[c]=nq;        }    }}void ins(int x,int y){    a[++len].y=y;    a[len].next=last[x];last[x]=len;}void pre(int x){    for(int i=last[x];i;i=a[i].next)    {        int y=a[i].y;        pre(y);ri[x]+=ri[y];    }}int main(){    int n;scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%s",ch+1);int len=strlen(ch+1);        for(int j=1;j<=len;j++) addsam(ch[j]-'a',++num),s[num]=ch[j];        addsam(27,++num);s[num]=27+'a';    }    for(int i=2;i<=tot;i++) ins(sam[i].par,i);    pre(1);    int p=1,x=root;    while(p<=num)    {        int c=s[p]-'a';        if(c==27)        {            printf("%d\n",ri[x]);            p++;x=root;            continue;        }        x=sam[x].a[c];p++;    }}


原创粉丝点击