题目描述

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

输入

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

输出

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

样例输入

3
a
aa
aaa

样例输出

6
3
1
 
这道题题干真是言简意赅,看了半天愣是没看明白。为了防止有人也像我一样没看懂,在这里解释下题目及样例:文章由输入的几个单词组成,但并不是把这几个字符串连一起。对于询问的第i个单词出现几次是指这个单词在每个单词中出现次数加和(包括自己)。例如样例中a在第一个单词中出现1次,在第二个中出现2次,在第三个中出现3次;aa在第一个中没有,第二个第三个中分别出现1次、2次。aaa只在第三个中出现1次。对于第i个单词在第j个单词中出现几次就相当于问j单词中有几个节点直接或间接指向i单词的终止节点,也就是问在fail树中以i单词终止节点为根的子树中有几个节点是j单词串上的点。fail树是什么?fail树就是由每个点失配标记连向这个点所形成的树。在建AC自动机时要记录每个点被遍历几次作为这个点的权值表示这个点是几个单词串上的点,最后dfs一遍fail树就好了。
最后附上代码。
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int num;
int tot;
int cnt;
int g[300];
char s[1000010];
int to[1000010];
int sum[1000010];
int fail[1000010];
int next[1000010];
int head[1000010];
int a[1000010][26];
void add(int x,int y)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void build(char *s)
{
int now=0;
int len=strlen(s);
for(int i=0;i<len;i++)
{
if(!a[now][s[i]-'a'])
{
a[now][s[i]-'a']=++cnt;
}
now=a[now][s[i]-'a'];
sum[now]++;
}
g[++num]=now;
}
void getfail()
{
queue<int>q;
for(int i=0;i<26;i++)
{
if(a[0][i])
{
fail[a[0][i]]=0;
q.push(a[0][i]);
}
}
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(a[now][i])
{
fail[a[now][i]]=a[fail[now]][i];
q.push(a[now][i]);
}
else
{
a[now][i]=a[fail[now]][i];
}
}
}
}
void dfs(int x)
{
for(int i=head[x];i;i=next[i])
{
dfs(to[i]);
sum[x]+=sum[to[i]];
}
return ;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
build(s);
}
getfail();
for(int i=1;i<=cnt;i++)
{
add(fail[i],i);
}
dfs(0);
for(int i=1;i<=n;i++)
{
printf("%d\n",sum[g[i]]);
}
}

BZOJ3172[Tjoi2013]单词——AC自动机(fail树)的更多相关文章

  1. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  2. BZOJ 3172 [Tjoi2013]单词 AC自动机Fail树

    题目链接:[http://www.lydsy.com/JudgeOnline/problem.php?id=3172] 题意:给出一个文章的所有单词,然后找出每个单词在文章中出现的次数,单词用标点符号 ...

  3. BZOJ2905: 背单词 AC自动机+fail树+线段树

    $zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...

  4. BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树

    Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...

  5. bzoj3172: [Tjoi2013]单词 ac自动机

    某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词 ...

  6. 【学习笔记】ac自动机&fail树

    定义 解决文本串和多个模式串匹配的问题: 本质是由多个模式串形成的一个字典树,由tie的意义知道:trie上的每一个节点都是一个模式串的前缀: 在trie上加入fail边,一个节点fail边指向这个节 ...

  7. 【BZOJ3172】[Tjoi2013]单词 AC自动机

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

  8. 【AC自动机/fail树】BZOJ3172- [Tjoi2013]单词

    [题目大意] http://www.lydsy.com:808/JudgeOnline/problem.php?id=3172 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多 ...

  9. AC自动机 & Fail树 专题练习

    Fail树就是AC自动机建出来的Fail指针构成的树. [bzoj3172][xsy1713]单词 题意 给定一些单词,求每个单词在所有单词里面的出现次数. 分析 构建Fail树,记录每个单词最后一个 ...

随机推荐

  1. 洛谷 P1546 最短网络 Agri-Net

    题目链接 https://www.luogu.org/problemnew/show/P1546 题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当 ...

  2. x509: certificate signed by unknown authority harbor 架构图

    默认时,client 与 Registry 的交互是通过 https 通信的.在 install Registry 时,若未配置任何tls 相关的 key 和 crt 文件,https 访问必然失败. ...

  3. java JDK安装教程

    JAVA_HOME G:\JDK\java7\jdk1.7.0_80    根据自己的哈     ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin 然后找到CLASSPATH ...

  4. (原创)odoo在docker环境下无法备份

    odoo容器内置postgresql-client版本和数据库版本不一致,安装和数据库版本相同或者更高版本的客户端 参考:https://www.postgresql.org/download/lin ...

  5. 数据库日志——mysql与Oracle的日志

    一.MySQL 在数据同步中用的比较多的是MySQL的binlog 1.bin-log简介 它记录了所有的DDL和DML(除了数据查询语句,select与show不记录)语句,以事件形式记录,还包含语 ...

  6. RabbmitMQ-Publish/Subscribe

    之前的学习中,我们了解的工作队列实现的是:一个消息只发送到一个消费者. 现在我们来学习一下新模式:发布/订阅模式 之前我们在原理中介绍了exchange,但好像并没有使用.而是直接往队列里发消息和取消 ...

  7. 安卓自动化测试案例(跑在MonkeyRunner上)

    首先文件所在目录: MonkeyRunner所在目录: 运行命令(通过cd 命令  进入Tools目录下): 运行脚本:monkeyrunner.bat ..\honeywell\jsq.py 源文件 ...

  8. Python从菜鸟到高手(1):初识Python

    1 Python简介 1.1 什么是Python   Python是一种面向对象的解释型计算机程序设计语言,由荷兰人吉多·范罗苏姆(Guido van Rossum)于1989年发明,第一个公开发行版 ...

  9. vs2013——单元测试&& 性能图

    一.如何创建单元测试 下面这个博客中写的很详细: http://***/Article/11186 其中需要注意的是,首先新建工程项目,在此目录下Add单元测试项目,还需要在单元测试项目中引用被测试的 ...

  10. 生命游戏&一维细胞自动机 笔记

    de 生命游戏是一种简单的聚合模型,展示了事物是如何聚合的,是自动机(CA)模型的一种.由剑桥大学约翰康威发明,其规则为: 1. 每个细胞拥有八个邻居,细胞状态只有存活(黑)和死亡(白)两种: 2.处 ...