[BZOJ3172][Tjoi2013]单词

来源:互联网 发布:mac 无法更新10.11.6 编辑:程序博客网 时间:2024/05/17 17:16

[Tjoi2013]单词

Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
3
a
aa
aaa
Sample Output
6
3
1

Solution:
首先我们构建出fail树。
由fail树的性质我们知道,对于fail树上的某一个结点p,都代表了trie里的一个串s,而这个结点的子树中的所有结点代表的字符串s’,都以该结点代表的字符串s为后缀。
因此,我们在建立trie的时候可以统计出每一个结点p代表的字符串s作为后缀出现了几次(只要在建trie的时候路过这个点就++这个点的cnt),再加上该结点在fail树中的子树里所有点的cnt就是答案了。

#include <bits/stdc++.h>#include <ext/pb_ds/tree_policy.hpp>#include <ext/pb_ds/hash_policy.hpp>#include <ext/pb_ds/priority_queue.hpp>#include <ext/pb_ds/assoc_container.hpp>using namespace std;typedef long long ll;typedef pair<int, int> PII;#define rep(i, l, r) for (int i = (l); i <= (r); i++)#define per(i, r, l) for (int i = (r); i >= (l); i--)#define REP(i, n) for (int i = 0; i < n; i++)#define fst first#define sec second#define MS(_) memset(_, 0, sizeof(_))#define PB push_back#define MP maketemplate<typename _T> inline void read(_T &x){    x = 0; bool f = 1; char ch = getchar();    while (!isdigit(ch)) {if (ch == '-') f = 0; ch = getchar();}    while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}    x = f ? x : -x;}const int N = 222;const int L = 1111111;struct Node{    Node *fail, *nxt[26]; int cnt;}pool[L<<1], *root, *tail = pool;char st[L];int q[L], pos[L], n, tot;inline void ins(Node *&rt, char *p, int no){    if (!rt) rt = tail++;    rt->cnt++;    if (!*p) pos[no] = (int)rt;    else ins(rt->nxt[*p-'a'], p+1, no);}inline void build(){ int l, r;    root->fail = root;    for (q[l = r = 1] = (int)root; l <= r; l++){        Node *p = (Node *)q[l];        REP(i, 26) if (p->nxt[i]) q[++r] = (int)p->nxt[i], p->nxt[i]->fail = p == root ? root : p->fail->nxt[i];                   else p->nxt[i] = p == root ? root : p->fail->nxt[i];    }    tot = r;}inline void dp(){     per(i, tot, 1){ Node *p = (Node *)q[i]; p->fail->cnt += p->cnt; } }int main(){    read(n);    rep(i, 1, n) scanf("%s", st), ins(root, st, i);    build();    dp();    rep(i, 1, n){ Node *p = (Node *)pos[i]; printf("%d\n", p->cnt); }    return 0;    }
0 0