首页 > 代码库 > BZOJ 3172: [Tjoi2013]单词 AC自动机

BZOJ 3172: [Tjoi2013]单词 AC自动机

3172: [Tjoi2013]单词


Description

某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。

Input

第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6

Output

输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。

Sample Input

3
a
aa
aaa

Sample Output

6
3
1

HINT

 

 

入门

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int N=1e6+10,mod=1e9+7,inf=2e9+10;int nex[N][27],head,tail,pos[N],cnt = 1,fail[N],sum[N],q[N],n;char a[N];void insert(char *s,int &x) {    int now = 1, len = strlen(s);    for(int i = 0; i < len; ++i) {        int index = s[i] - a;        if(!nex[now][index]) nex[now][index] = ++cnt;        now = nex[now][index];        sum[now]++;    }    x = now;}void build_fail() {    head = 0,tail = 0;    q[tail++] = 1;    fail[1] = 0;    while(head != tail) {        int now = q[head++];        for(int i = 0; i < 26; ++i) {            if(!nex[now][i]) continue;            int p = fail[now];            while(!nex[p][i]) p = fail[p];            fail[nex[now][i]] = nex[p][i];            q[tail++] = nex[now][i];        }    }}int main() {    for(int i = 0; i < 26; ++i) nex[0][i] = 1;    scanf("%d",&n);    for(int i = 1; i <= n; ++i) {        scanf("%s",a);        insert(a,pos[i]);    }//cout<<1<<endl;    build_fail();    for(int i = tail-1; i >=0; --i) sum[fail[q[i]]] += sum[q[i]];    for(int i = 1; i <= n; ++i) cout<<sum[pos[i]]<<endl;    return 0;}

 

BZOJ 3172: [Tjoi2013]单词 AC自动机