BZOJ 3172 [Tjoi2013]单词 AC自动机Fail树
题目链接:【http://www.lydsy.com/JudgeOnline/problem.php?id=3172】
题意:给出一个文章的所有单词,然后找出每个单词在文章中出现的次数,单词用标点符号隔开。
题解:时间很坑啊,朴素的做法是,先在AC自动机上插入单词,并记录下每个单词,然后用每个单词去维护答案。但是这样做时间空间都不允许,只有在插入的时候维护答案。过程是这样的,在插入的时候,每经过一个点,该节点的值加一,同时记录单词末尾的位置,然后在求玩Fail的时候,倒着走回去就可以了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2024 * 1024 + 15;
char tmp[maxn];
struct Aho_C
{
int Next[maxn][26], Fail[maxn], pos[maxn], cnt[maxn];
int que[maxn], st, ed;
int root, sz;
int newnode()
{
for(int i = 0; i < 26; i++) Next[sz][i] = 0;
cnt[sz] = 0;
sz++;
return sz - 1 ;
}
void init()
{
sz = 0;
root = newnode();
}
void Insert(char buf[], int id)
{
int len = strlen(buf);
int now = root;
for(int i = 0; i < len; i++)
{
if(!Next[now][buf[i] - 'a'])
Next[now][buf[i] - 'a'] = newnode();
now = Next[now][buf[i] - 'a'];
cnt[now]++;
}
pos[id] = now;
}
void getFail()
{
st = ed = 1;
for(int i = 0; i < 26; i++)
if(Next[root][i])
que[ed++] = Next[root][i];
while(st != ed)
{
int u = que[st++];
for(int i = 0; i < 26; i++)
{
int &v = Next[u][i];
if(!v)
{
v = Next[Fail[u]][i];
continue;
}
Fail[v] = Next[Fail[u]][i];
que[ed++] = v;
}
}
for(int i = ed - 1; i >= 1; i--) cnt[Fail[que[i]]] += cnt[que[i]];
}
} ac;
int main()
{
int N;
scanf("%d", &N);
ac.init();
for(int i = 1; i <= N; i++)
{
scanf("%s", tmp);
ac.Insert(tmp, i);
}
ac.getFail();
for(int i = 1; i <= N; i++) printf("%d\n", ac.cnt[ac.pos[i]]);
return 0;
}
BZOJ 3172 [Tjoi2013]单词 AC自动机Fail树的更多相关文章
- BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3198 Solved: 1532[Submit][Status ...
- bzoj 3172: [Tjoi2013]单词 AC自动机
3172: [Tjoi2013]单词 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树
Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...
- BZOJ3172[Tjoi2013]单词——AC自动机(fail树)
题目描述 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次. 输入 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个 ...
- BZOJ 3172 [Tjoi2013]单词 AC自己主动机(fail树)
题意:链接 方法:AC自己主动机与fail树性质 解析:复习AC自己主动机的第一道题?(真正的第一题明明是又一次写了遍hdu2222! ) 这题说实话第一眼看上去就是个sb题,仅仅要建出来自己主动机. ...
- BZOJ2905: 背单词 AC自动机+fail树+线段树
$zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...
- bzoj 3172 [Tjoi2013]单词(fail树,DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3172 [题意] 题目的意思是这样的,给若干个单词,求每个单词在这一堆单词中的出现次数. ...
- 【学习笔记】ac自动机&fail树
定义 解决文本串和多个模式串匹配的问题: 本质是由多个模式串形成的一个字典树,由tie的意义知道:trie上的每一个节点都是一个模式串的前缀: 在trie上加入fail边,一个节点fail边指向这个节 ...
- BZOJ 3172([Tjoi2013]单词-后缀数组第一题+RMQ)
3172: [Tjoi2013]单词 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 268 Solved: 145 [ Submit][ St ...
随机推荐
- Oracle错误: ORA-01722 无效数字
ORA-01722: 无效数字 主要原因是: 1.对于两个类型不匹配(一个数字类型,一个非数字类型,同下)的值进行赋值操作; 2.两个类型不匹配的值进行比较操作(例如,"="); ...
- glut glew区别
GLEW是一个跨平台的C++扩展库,基于OpenGL图形接口.使用OpenGL的朋友都知道,window目前只支持OpenGL1.1的涵数,但 OpenGL现在都发展到2.0以上了,要使用这些Open ...
- mybatis模糊查询防止SQL注入
SQL注入,大家都不陌生,是一种常见的攻击方式.攻击者在界面的表单信息或URL上输入一些奇怪的SQL片段(例如“or ‘1’=’1’”这样的语句),有可能入侵参数检验不足的应用程序.所以,在我们的应用 ...
- Strusts2笔记4--类型转换器
类型转换器: Struts2默认情况下可以将表单中输入的文本数据转换为相应的基本数据类型.这个功能的实现,主要是由于Struts2内置了类型转换器.这些转换器在struts-default.xml中可 ...
- 深拷贝数组 np.copy
数组对象自带了浅拷贝和深拷贝的方法,但是一般用深拷贝多一些: 代码如下: >>> a = np.ones((2,2)) >>> b = a >>> ...
- 15 Defer, Panic, and Recover
Defer, Panic, and Recover 4 August 2010 Go has the usual mechanisms for control flow: if, for, switc ...
- 原生JS实现AJAX、JSONP及DOM加载完成事件
一.JS原生Ajax ajax:一种请求数据的方式,不需要刷新整个页面:ajax的技术核心是 XMLHttpRequest 对象:ajax 请求过程:创建 XMLHttpRequest 对象.连接服务 ...
- 基于gRpc的远程服务框架
作为一个新搭建的软件团队,底层技术尤为重要.为了以后更好的面向不同的项目需求,满足不断变化的需求,决定着手搭建一套RPC系统.为了更好的兼容以后部门其他语言的使用,选择了开源框架gRpc. gRpc ...
- kickstart配置LINUX无人值守选项--rootpw
linux kickstart rootpw密码可以使用明文,也可以使用加密过的值(密码为:IPPBXADMINROOT) 注意:在这里要使用加密过的值,否则安全性就太低了 rootpw --iscr ...
- LeetCode664. Strange Printer
There is a strange printer with the following two special requirements: The printer can only print a ...