3172: [Tjoi2013]单词
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2109 Solved: 978
[ Submit][ Status][ Discuss]
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
a
aa
aaa
Sample Output
3
1
解题思路:
首先先跑一遍AC自动机,然后记录下每个点的失配边所连其它点,然后确定主串后,进行一次匹配,并且把每次在的点的sum+1;最后对n个单词进行一次BFS统计其它连与它,或间接连与它的点的sum就可以了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int uk;
char c[1100001];
char s[2100001];
const int M_ax=1100001;
int lw=0;
struct data
{
int to,next;
}e[2100001];
int h[1100001];
int v[211];
bool ch[1100001][26];
int dui[1100001][26];
int f[1100001];
int q[1100001];
int summ[1100001];
int now_sum;
void insert(int x,int y)
{
++lw;
e[lw].to=y;
e[lw].next=h[x];
h[x]=lw;
}
int change(char c)
{
int sug=int(c)-96;
return sug;
}
void dfs(int now,int len,int xian,int o)
{
if (len>xian) {v[o]=now;return;}
int zan=change(c[len-1]);
if (ch[now][zan])
{
dfs(dui[now][zan],len+1,xian,o);
}else
{
ch[now][zan]=true; ++now_sum;
dui[now][zan]=now_sum;
dfs(now_sum,len+1,xian,o);
}
}
void Init(int o)
{
getchar();
scanf("%s",c); int len=strlen(c);
for (int i=0;i<=len-1;++i)
{
++uk;
s[uk]=c[i];
}
++uk; s[uk]='-';
dfs(0,1,len,o);
}
void ready()
{
f[0]=-1; int tail=1; int head=0; q[tail]=0;
while (head!=tail)
{
head=(head+1)%M_ax;
for (int i=1;i<=26;++i)
if (ch[q[head]][i])
{
int now=f[q[head]];
while (now!=-1 && !ch[now][i])
{
now=f[now];
}
if (now==-1) now=0;else now=dui[now][i];
f[dui[q[head]][i]]=now; insert(now,dui[q[head]][i]);
tail=(tail+1)%M_ax;
q[tail]=dui[q[head]][i];
}
}
}
int main()
{
uk=0;
scanf("%d",&n); now_sum=0;
for (int i=1;i<=n;++i)
{
Init(i);
}
--uk;
ready();
int now=0;
for (int i=1;i<=uk;++i)
{
int zan=change(s[i]);
if (s[i]=='-')
{
now=0; continue;
}
while (now!=-1 && !ch[now][zan]) now=f[now];
if (now!=-1)
{
++summ[dui[now][zan]];
now=dui[now][zan];
}else now=0;
}
for (int i=1;i<=n;++i)
{
int now=v[i];
long long sug=0;
int tail=1; int head=0; q[tail]=v[i];
while (head!=tail)
{
head=(head+1)%M_ax;
sug+=summ[q[head]];
int u=h[q[head]];
while (u!=0)
{
tail=(tail+1)%M_ax;
q[tail]=e[u].to;
u=e[u].next;
}
}
cout<<sug<<endl;
}
}