BZOJ3172[Tjoi2013]单词 题解

题目大意:

求一些字符串在一段文章中出现的次数。

思路:

AC自动机的经典应用,建完自动机直接将队列里的元素调Fail指针记录即可。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 #define M 1000009
 6 #define FC x==0?0:child[fail[x]][i]
 7 char s[M];
 8 int head,tail,cnt,q[M],sum[M],id[M],child[M][26],fail[M];
 9
10 void ins(int &x)
11 {
12     for (int i=0,j;i<strlen(s);i++,x=child[x][j],sum[x]++)
13         if (!child[x][j=s[i]-‘a‘]) child[x][j]=++cnt;
14 }
15
16 void build()
17 {
18     for (head=0,tail=1;head<tail;)
19     {
20         int x=q[++head],i;
21         for (i=0;i<26;i++)
22             if (child[x][i]) q[++tail]=child[x][i],fail[child[x][i]]=FC;
23             else child[x][i]=FC;
24     }
25 }
26
27 int main()
28 {
29     int n,i;
30     scanf("%d",&n);
31     for (i=1;i<=n;i++) scanf("%s",s),ins(id[i]);
32     for (build(),i=tail;i;i--) sum[fail[q[i]]]+=sum[q[i]];
33     for (i=1;i<=n;i++) printf("%d\n",sum[id[i]]);
34 }
时间: 2024-08-03 16:54:50

BZOJ3172[Tjoi2013]单词 题解的相关文章

BZOJ-3172: [Tjoi2013]单词 (AC自动姬)

3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 4057  Solved: 1964[Submit][Status][Discuss] Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词由小写字母组成,N<=200,单词长度不超过10^6

[Bzoj3172][Tjoi2013]单词(fail树)

3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 4777  Solved: 2345[Submit][Status][Discuss] Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词由小写字母组成,N<=200,单词长度不超过10^6

[bzoj3172][Tjoi2013]单词——AC自动机

题目大意: 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. 思路: 第i个单词在整个文章中出现了多少次即i串的结尾可以被多少个串的节点给跳到. 于是吧fail看成每个节点唯一的父亲,每个节点的权值为有多少个单词的前缀经过了它,然后直接统计子树内的权值和即可. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++

bzoj3172 [Tjoi2013]单词

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3172 [题解] 考虑建出AC自动机,那么fail树上每个点的父亲为fail,父亲->儿子为后缀关系(父亲是儿子后缀) 那么走到父亲肯定走到了儿子,直接统计即可. # include <queue> # include <stdio.h> # include <string.h> # include <iostream> # include <

[BZOJ3172 ][Tjoi2013]单词(AC自动机)

Description 不稳定的传送门 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次.单词个数<=200,单词总长度<=10^6 Solution AC自动机的入门题,将所有单词建一颗字典树,并构造fail树 然后随便统计一下数量就可以了 Code #include <cstdio> #include <algorithm> #include <cstring> #define R re

【bzoj3172】: [Tjoi2013]单词 字符串-AC自动机

[bzoj3172]: [Tjoi2013]单词 先用所有单词构造一个AC自动机 题目要求的是每个单词在这个AC自动机里匹配到的次数 每次insert一个单词的时候把路径上的cnt++ 那么点p->cnt就是以root到p这条路径为前缀的单词的个数 如果p->fail指向了点q,那么就会对q点产生p->cnt的贡献(root到q一定为root到p的后缀) 最后递推统计完所有fail的贡献,找到关键点输出就可以了 1 /* http://www.cnblogs.com/karl07/ */

3172: [Tjoi2013]单词

3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1424  Solved: 653[Submit][Status] Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词由小写字母组成,N<=200,单词长度不超过10^6 Output 输出N

【BZOJ3172】单词(AC自动机)

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

#3831 TJOI2013单词

WOJ#3831 TJOI2013单词 题面 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. 输入 第一个一个整数 N ,表示有多少个单词,接下来 N 行每行一个单词. 输出 输出 N 个整数,第 i 行的数字表示第 i 个单词在文章中出现了多少次. 样例输入 3 a aa aaa 样例输出 6 3 1 提示 对于全部数据,1≤N≤200 ,所有单词长度的和不超过 106,保证每个单词由小写字母组成. 题解 本题中,第2行到