bzoj3172 [Tjoi2013]单词

来源:互联网 发布:开展数据库培训 编辑:程序博客网 时间:2024/05/29 13:50

传送门
Description

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

Input

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

Output

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

Sample Input

3

a

aa

aaa
Sample Output

6

3

1

同样是裸的AC自动机,不过处理有点蛋疼。。。一开始处理的不太好结果导致时间是别人的4倍QAQ

CODE:

#include<cstdio>#include<cstring>struct queue{    int h,t;    int a[1000001];    void clear() {h=1,t=0;}    void push(int n) {a[++t]=n;}    int front() {return a[h];}    void pop() {h++;}    bool empty() {return h>t;}}q;struct AC{    int ch[26];    int fail,cnt;}a[1000001];;char s[1000001];int pos[201];int n,tot;inline void init(){    q.clear();    a[0].fail=-1;}inline void insert(char *s,int d){    int now=0,p,len=strlen(s);    for(int i=0;i<len;i++)    {        p=s[i]-'a';        if(!a[now].ch[p]) a[now].ch[p]=++tot;        now=a[now].ch[p];        a[now].cnt++;    }    pos[d]=now;}inline void makefail(){    q.push(0);    while(!q.empty())    {        int now=q.front();        q.pop();        for(int i=0;i<26;i++)          if(a[now].ch[i])          {            int p=a[now].fail;            while(p!=-1&&!a[p].ch[i]) p=a[p].fail;            if(p==-1) a[a[now].ch[i]].fail=0;            else a[a[now].ch[i]].fail=a[p].ch[i];            q.push(a[now].ch[i]);          }    }    for(int i=q.t;i>=1;i--)      a[a[q.a[i]].fail].cnt+=a[q.a[i]].cnt;}int main(){    scanf("%d",&n);    init();    for(int i=1;i<=n;i++)      scanf("%s",s),insert(s,i);    makefail();    for(int i=1;i<=n;i++)      printf("%d\n",a[pos[i]].cnt);    return 0;}
0 0
原创粉丝点击