转载请注明出处:http://blog.csdn.net/vmurder/article/details/42711351
其实我就是觉得原创的访问量比未授权盗版多有点不爽233。。。
题解:水爆了,直接AC自动机瞎写就行。
坑:……时隔一个半月的感动AC,竟然是因为这道题可以有重复单词233。
代码:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001000
#define M 205
#define T 27
#define inf 0x3f3f3f3f
using namespace std;
struct KSD
{
int v,next;
}e[M];
int head[N],tot;
inline void add(int u,int v)
{
e[++tot].v=v;
e[tot].next=head[u];
head[u]=tot;
}
char s[N];
int begin[M],end[M],n; // 左闭右开
int ans[N];
struct ACAUTO
{
int next[N][T],fail[N],flag[N],cnt;
void insert(int id,int l,int r)
{
int i,x,alp;
for(x=0,i=l;i<=r;i++)
{
alp=s[i]-'a';
if(!next[x][alp])next[x][alp]=++cnt;
x=next[x][alp];
}
add(x,id);
}
int stk[N],top;
void build()
{
queue<int>q;
q.push(0);
int i,u,v;
while(!q.empty())
{
u=q.front(),q.pop();
stk[++top]=u;
for(i=0;i<T;i++)
{
if(v=next[u][i])
{
if(!u)fail[v]=0;
else fail[v]=next[fail[u]][i];
q.push(v);
}
else next[u][i]=next[fail[u]][i];
}
}
}
int f[N];
void find()
{
int i,x,alp;
for(i=0;i<end[n];i++)
{
if(s[i]=='$')
{
x=0;
continue;
}
alp=s[i]-'a';
f[x=next[x][alp]]++;
}
}
void dp()
{
int i,u,v;
while(top)
{
u=stk[top--];
for(i=head[u];i;i=e[i].next)
ans[e[i].v]+=f[u];
f[fail[u]]+=f[u];
}
}
}acauto;
int main()
{
// freopen("test.in","r",stdin);
int i,j,k;
scanf("%d",&n);
end[0]=-1;
for(i=1;i<=n;i++)
{
s[++end[i-1]]='$';
begin[i]=end[i-1]+1;
scanf("%s",s+begin[i]);
end[i]=end[i-1]+strlen(s+begin[i]);
acauto.insert(i,begin[i],end[i]);
}end[n]++;
acauto.build();
acauto.find();
acauto.dp();
for(i=1;i<=n;i++)printf("%d\n",ans[i]);
return 0;
}