[TJOI2013]单词(AC自动机+前缀和维护)

链接:https://ac.nowcoder.com/acm/problem/20443
来源:牛客网

题目描述

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

输入描述:

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

输出描述:

输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
具体思路:首先在trie树上每次添加一个节点,这个节点的权值就+1,保存每个字符串最终节点在trie树上的编号。然后再去建立fail指针。当建立好fail指针的时候,跑一遍前缀和。
具体跑前缀和的时候,每一个节点更新到这个节点的fail指针上就好了。
AC代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 const int mod = 1e9+7;
 5 const int maxn = 1e6+100;
 6 int ch[maxn][30],tot=0;
 7 char str[200+10][maxn];
 8 int val[maxn];
 9 int ans[maxn];
10 int  add_trie(char st[])
11 {
12     int len=strlen(st);
13     int p=0;
14     for(int i=0; i<len; i++)
15     {
16         int to=st[i]-'a';
17         if(!ch[p][to])
18             ch[p][to]=++tot;
19         p=ch[p][to];
20         val[p]++;
21     }
22     return p;
23 }
24 int fail[maxn],last[maxn];
25 int sto[maxn];
26 int num=0;
27 void get_fail()
28 {
29     queue<int>q;
30     for(int i=0; i<=tot; i++)
31         fail[i]=-1;
32     q.push(0);
33     while(!q.empty())
34     {
35         int top=q.front();
36         q.pop();
37         for(int i=0; i<26; i++)
38         {
39             int u=ch[top][i];
40             if(u==0)
41                 continue;
42             sto[++num]=u;
43             q.push(u);
44             int v=fail[top];
45             while(v!=-1&&!ch[v][i])
46                 v=fail[v];
47             fail[u]=(v==-1?0:ch[v][i]);
48             last[u]=val[fail[u]]?fail[u]:last[fail[u]];
49         }
50     }
51 }
52 int n;
53 void init()
54 {
55     for(int i=num; i>=1; i--)
56     {
57         val[fail[sto[i]]]+=val[sto[i]];
58     }
59 }
60 void print()
61 {
62     for(int i=1; i<=n; i++)
63     {
64         printf("%d\n",val[ans[i]]);
65     }
66 }
67 int main()
68 {
69     scanf("%d",&n);
70     for(int i=1; i<=n; i++)
71     {
72         scanf("%s",str[i]);
73         ans[i] = add_trie(str[i]);
74     }
75     get_fail();
76     init();
77     print();
78     return 0;
79 }

 



posted @ 2019-05-16 17:47  Let_Life_Stop  阅读(356)  评论(0编辑  收藏  举报