AC自动机
Orz zyf
玛雅一开始连题意都没看懂……意思就是给你一篇文章的N个单词,问每个单词在这篇文章中各出现了几次?(这篇文章=N个单词)
那么我们建个AC自动机……对于每个单词来说,它出现的次数=以它为根的fail树的大小,即询问有多少点沿fail指针能走到这个单词的结束结点。
但是我们有更简单的算法= =(orz zyf)
AC自动机的话我们直接其实就是查询有多少个节点通过fail能到达该串的结束节点,既然这样符合条件的一定bfs的时候在该点之后
那么我们按bfs逆序执行w[go[i]]+=w[i]即可。正确性显然。
/**************************************************************
Problem: 3172
User: Tunix
Language: C++
Result: Accepted
Time:4432 ms
Memory:119436 kb
****************************************************************/ //BZOJ 3172
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=1e6+,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int n,cnt=,pos[N];
struct Trie{
int ch[],fail,w;
}T[N];
char s[N];
void ins(char *s,int num){
int x=,y;
rep(i,strlen(s)){
y=s[i]-'a';
if (!T[x].ch[y]) T[x].ch[y]=++cnt;
x=T[x].ch[y];
T[x].w++;
}
pos[num]=x;
}
int Q[N],l=,r=-;
void make_fail(){
Q[++r]=;
while(l<=r){
int x=Q[l++],y,j;
rep(i,){
j=T[x].fail;
while(j && !T[j].ch[i]) j=T[j].fail;
if (T[x].ch[i]){
y=T[x].ch[i];
T[y].fail=j ? T[j].ch[i] : ;
Q[++r]=y;
}else T[x].ch[i]=j ? T[j].ch[i] : ;
}
}
} int main(){
#ifndef ONLINE_JUDGE
freopen("3172.in","r",stdin);
freopen("3172.out","w",stdout);
#endif
n=getint(); cnt=;
F(i,,n){
scanf("%s",s);
ins(s,i);
}
make_fail();
D(i,r,) T[T[Q[i]].fail].w+=T[Q[i]].w;
F(i,,n) printf("%d\n",T[pos[i]].w);
return ;
}
3172: [Tjoi2013]单词
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 1573 Solved: 723
[Submit][Status][Discuss]
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
3
a
aa
aaa
a
aa
aaa
Sample Output
6
3
1
3
1
HINT
Source