[BZOJ3172]TJOI2013单词|AC自动机

来源:互联网 发布:电脑行为监控软件 编辑:程序博客网 时间:2024/04/29 17:27

这题比阿狸的打字机不知道简单多了。。还是弄出fail树来 root到每个串的路径上的点都标记+1,统计i串的danger节点在fail树上的子树上的标记个数就是它出现的次数。。

#include<iostream>#include<cstdio>#include<memory.h>#define N 2000005int n,i,nd=1,next[N],a[N][28],size[N],pos[N],que[N];char s[N];int ins(char *s){  int now=1;  for (int i=0;i<strlen(s);i++){  if (!a[now][s[i]-'a']) a[now][s[i]-'a']=++nd;  now=a[now][s[i]-'a'];  size[now]++;}  return now;}void build(){  int head=1,tail=1,get,i,now;  que[1]=1;  while(head<=tail){  get=que[head++];  for (i=0;i<26;i++)if (a[get][i])  {que[++tail]=a[get][i];now=next[get];while (!a[now][i]) now=next[now];next[a[get][i]]=a[now][i];  }}  for (i=tail;i>1;i--) size[next[que[i]]]+=size[que[i]];}int main(){  scanf("%d",&n);  memset(a,0,sizeof(a));  memset(size,0,sizeof(size));  for (i=0;i<26;i++) a[0][i]=1;  next[1]=0;  for (i=1;i<=n;i++){  scanf("%s",s);  pos[i]=ins(s);}  build();  for (i=1;i<=n;i++)printf("%d\n",size[pos[i]]);}


0 0