3172: [Tjoi2013]单词

来源:互联网 发布:java常用集合 编辑:程序博客网 时间:2024/05/17 06:24

3172: [Tjoi2013]单词

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 2968  Solved: 1422
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

Sample Input

3
a
aa
aaa

Sample Output

6
3
1

HINT

Source

[Submit][Status][Discuss]



构造一个AC自动机

每个点的权值记为包含它的单词数

ans就是fail-tree上的子树权值和

#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<bitset>#include<algorithm>#include<cstring>#include<map>#include<stack>#include<set>#include<cmath>#include<ext/pb_ds/priority_queue.hpp>using namespace std;const int maxn = 1E6 + 10;typedef long long LL;int n,len,cnt,pos[210],ch[maxn][26],fail[maxn];LL Siz[maxn];char c[maxn];queue <int> Q;vector <int> v[maxn];void DFS(int x){for (int i = 0; i < v[x].size(); i++) {int to = v[x][i];DFS(to);Siz[x] += Siz[to];}}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> n;for (int i = 1; i <= n; i++) {scanf("%s",c + 1);len = strlen(c + 1);int now = 0;for (int j = 1; j <= len; j++) {int Nex = c[j] - 'a';if (!ch[now][Nex]) ch[now][Nex] = ++cnt;now = ch[now][Nex]; ++Siz[now];}pos[i] = now;}for (int i = 0; i < 26; i++)if (ch[0][i]) {Q.push(ch[0][i]);fail[ch[0][i]] = 0;v[0].push_back(ch[0][i]);}while (!Q.empty()) {int k = Q.front(); Q.pop();for (int i = 0; i < 26; i++) {int u = ch[k][i];if (!u) continue;int F = fail[k];while (F && !ch[F][i]) F = fail[F];fail[u] = ch[F][i]; v[fail[u]].push_back(u);Q.push(u);}}DFS(0);for (int i = 1; i <= n; i++) printf("%lld\n",Siz[pos[i]]);return 0;}

0 0
原创粉丝点击