「BZOJ 2434」「NOI 2011」阿狸的打字机「AC自动机」
题意
有一个打字机,支持三种操作:
- 字符串末尾加一个小写字母
- 字符串末尾减一个字符
- 输出这个字符串
经过不超过\(n\)次操作后有\(m\)组询问:\((x,y)\),表示第\(x\)次输出第字符串在第\(y\)次输出第字符串里出现几次
\(n,m \leq 10^5\)
题解
每次加减字符就在trie树上走,输出的话记录一下在哪个结点
然后考虑询问\((x,y)\)暴力怎么做:\(x\)应该是\(y\)一个前缀的后缀,于是我们对于从根到\(y\)路径上每个结点(这相当于枚举\(y\)的后缀),从这个结点跳\(fail\),如果跳到\(x\)就\(ans++\),然后考虑下一个结点
实际上我们要求的就是根到\(y\)这条链上的结点中,在\(fail\)树中是\(x\)儿子的个数
我们可以按\(\text{trie}\)树的\(\text{dfs}\)序枚举\(y\),这样枚举所有的链和信息是\(O(n)\)的,每个点只会被加入一次和删除一次。然后考虑回答所有\((i,y)\)的询问,直接询问当前在\(x\)的\(fail\)树子树的结点个数。可以使用树状数组维护。具体说就是把询问按\(y\)在\(trie\)上的\(\text{dfs}\)序排序,然后每个点必须插入到它\(fail\)树\(\text{dfs}\)序的位置,查询就找到\(x\)的\(fail\)子树的\(\text{dfs}\)区间进行查询。
实现的话注意\(trie\)和\(fail\)不要搞混了,另外这题可以用主席树在线做
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int N = 2e5 + 10;
int ch[N][26], fa[N], fail[N];
int dfn[N], dl[N], dr[N], dn[N];
int pos = 1, id = 1, n, pt[N], ans[N];
vector<int> fs[N];
struct qs {
int x, y, id;
bool operator < (const qs &b) const {
return dfn[y] < dfn[b.y];
}
} q[N];
void work(char c) {
if(c == 'B') pos = fa[pos];
else if(c == 'P') pt[++ pt[0]] = pos;
else {
int &v = ch[pos][c - 'a'];
if(!v) {
v = ++ id;
fa[v] = pos;
}
pos = v;
}
}
void dfs(int u) { //on trie
dfn[u] = ++ dfn[0]; dn[dfn[0]] = u;
for(int i = 0; i < 26; i ++)
if(ch[u][i]) dfs(ch[u][i]);
}
void buildac() {
static int q[N], l, r, v;
for(int i = 0; i < 26; i ++) if(v = ch[1][i]) {
q[r ++] = v; fail[v] = 1;
} else ch[1][i] = 1;
while(l < r) {
int u = q[l ++];
for(int i = 0; i < 26; i ++) if(v = ch[u][i]) {
q[r ++] = v; fail[v] = ch[fail[u]][i];
} else ch[u][i] = ch[fail[u]][i];
}
for(int i = 2; i <= id; i ++)
fs[fail[i]].push_back(i);
}
void dfs2(int u) { //on fail tree
dl[u] = ++ dl[0];
for(int i = 0; i < fs[u].size(); i ++) dfs2(fs[u][i]);
dr[u] = dl[0];
}
int bit[N];
void add(int x, int y) {
for(; x <= id; x += x & (-x)) bit[x] += y;
}
int qry(int x) {
int ans = 0;
for(; x >= 1; x &= x - 1) ans += bit[x];
return ans;
}
int main() {
static char s[N]; scanf("%s", s);
for(char *c = s; *c; c ++) work(*c);
dfs(1); buildac(); dfs2(1);
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%d%d", &q[i].x, &q[i].y);
q[i].x = pt[q[i].x];
q[i].y = pt[q[i].y]; //id -> node
q[i].id = i;
}
sort(q + 1, q + n + 1);
for(int i = 1, j = 1; i <= id; i ++) {
int u = dn[i];
if(i > 1) {
int la = dn[i - 1];
while(la != fa[u]) {
add(dl[la], -1);
la = fa[la];
}
}
add(dl[u], 1);
for(; j <= n && dfn[q[j].y] == i; j ++) {
ans[q[j].id] = qry(dr[q[j].x]) - qry(dl[q[j].x] - 1);
}
}
for(int i = 1; i <= n; i ++)
printf("%d\n", ans[i]);
return 0;
}
「BZOJ 2434」「NOI 2011」阿狸的打字机「AC自动机」的更多相关文章
- 【BZOJ 2434】【NOI 2011】阿狸的打字机 fail树
完全不会啊,看题解还看了好久,我是蒟蒻$QAQ$ $zyf$的题解挺好的:http://blog.csdn.net/clove_unique/article/details/51059425 $fai ...
- BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题目大意] 给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串 ...
- NOI 2011 阿狸的打字机(AC自动机+主席树)
题意 https://loj.ac/problem/2444 思路 多串匹配,考虑 \(\text{AC}\) 自动机.模拟打字的过程,先建出一棵 \(\text{Trie}\) 树,把它变成自动机 ...
- 【NOI 2011】阿狸的打字机
Problem Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B . P 两个字母. ...
- NOI 2011 【阿狸的打字机】
之前讲了[AC自动姬],今天我终于把这题给刚下来了...嗯,来给大家讲一讲. 题目描述: 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工 ...
- 「AC自动机」学习笔记
AC自动机(Aho-Corasick Automaton),虽然不能够帮你自动AC,但是真的还是非常神奇的一个数据结构.AC自动机用来处理多模式串匹配问题,可以看做是KMP(单模式串匹配问题)的升级版 ...
- 「BZOJ 4228」Tibbar的后花园
「BZOJ 4228」Tibbar的后花园 Please contact lydsy2012@163.com! 警告 解题思路 可以证明最终的图中所有点的度数都 \(< 3\) ,且不存在环长是 ...
- 「BZOJ 3645」小朋友与二叉树
「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...
- 「BZOJ 4502」串
「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...
随机推荐
- 搭建Easyui环境在Myeclipse或Eclipse中
转自:https://www.cnblogs.com/henuyuxiang/p/4283018.html 1.下载Easyui.网址:http://www.jeasyui.com/download/ ...
- JPA 注解详解
@Entity --声明为一个实体类bean @Table (name= "promotion_info" ) --为实体bean映射指定表(表名="promotion_ ...
- 教你实现GPUImage - OpenGL渲染原理<转>
http://www.open-open.com/lib/view/open1483943550976.html
- Spring Cloud Zuul 1(API 网关服务)
API网关是一个更为智能的应用服务器,它的存在就像是整个微服架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤. 它实现的功能包括:请求路由.负载均衡.校验过滤等功能. Spring ...
- Scala中的函数
Scala中的函数 提纲 1.Scala中的函数简介 2.Scala中的函数的各种写法 1.Scala中的函数简介 =================== Scala是函数式编程和面向对象式编程的混合 ...
- node.js开发指南读书笔记(1)
3.1 开始使用Node.js编程 3.1.1 Hello World 将以下源代码保存到helloworld.js文件中 console.log('Hello World!'); console.l ...
- IDEA MAVEN 1.8无效的源发行版
最近想将自己在IDEA上开发的MAVEN项目切换到JDK1.8版本上,结果IDEA报1.8无效的源发行版.下面说一下自己的解决方案: 1.pom文件 <build> <plugins ...
- Linux 安装lamp
安装软件包编译器 gcc -v 查看是否存在 yum -y install gcc gcc-c++ mack rpm -q httpd 查看是否安装http rpm -e httpd --nodeps ...
- XP下,移动窗口产生重影的问题
最近做了一个东西,其中有一个小窗口需要跟着主窗口一起移动,结果发现在Xp系统上总是产生重影,需要刷新桌面才能消失. 移动窗口我使用的是MoveWindow,最后一个参数bRepaint传递的是FALS ...
- SpringBoot23 分模块开发
1 开发环境说明 JDK:1.8 MAVEN:3.5 IDEA:2017.2.5 SpringBoot:2.0.3.RELEASE 2 创建SpringBoot项目 2.1 项目信息 2.2 添加项目 ...