AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3172
【题解】
很裸的AC自动机。
pos记录一下字符串结束的位置,每个结点初始权值都为1,结点的fail指针指向的点的权值要加上这个结点的权值。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
#define MAXN 1000010
int n,cnt,v[MAXN],pos[MAXN],q[MAXN],fail[MAXN],tr[MAXN][27];
char ch[MAXN];
void insert(int &now)
{
now=0;
for(int i=1;i<=strlen(ch+1);i++)
{
if(!tr[now][ch[i]-'a']) tr[now][ch[i]-'a']=++cnt;
now=tr[now][ch[i]-'a'];
v[now]++;
}
}
void build()
{
int head=0,tail=0;
for(int i=0;i<26;i++) if(tr[0][i]) q[++tail]=tr[0][i];
while(++head<=tail)
{
int x=q[head];
for(int i=0;i<26;i++)
{
int y=tr[x][i];
if(!y) continue;
q[++tail]=y;
int temp=fail[x];
while(temp&&!tr[temp][i]) temp=fail[temp];
fail[y]=tr[temp][i];
}
}
for(int i=tail;i;i--) v[fail[q[i]]]+=v[q[i]];
}
int main()
{
//freopen("cin.in","r",stdin);
//freopen("cout.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) {scanf("%s",ch+1); insert(pos[i]);}
build();
for(int i=1;i<=n;i++) printf("%d\n",v[pos[i]]);
return 0;
}