【BZOJ】2434: [Noi2011]阿狸的打字机
题意
给你一些字符串。\(m\)次询问,每一次询问第\(x\)个字符串在\(y\)字符串中出现了多少次。(输入总长$ \le 10^5$, \(M \le 10^5\))
分析
在ac自动机上,\(x\)字符串出现的所有位置就是其它节点的fail树上有这个节点的节点。即fail树中,\(x\)字符串终止节点的子树。
题解
根据分析,我们只要构造ac自动机和fail树,按dfs序依次便历ac自动机,将节点到根的路径打上标记。每到一个终止节点,就更新以这个节点为模板的匹配串的答案,即这些节点子树的和。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
char buf[20*N], *is=buf;
int ihead[N], cnt, last[N], c[N][26], fail[N], pos[N], FF[N], LL[N], tot, su[N], ans[N];
inline bool isdig(const char &c) {
return c>='0'&&c<='9';
}
inline bool isok(const char &c) {
return (c>='a'&&c<='z')||c=='P'||c=='B';
}
inline int getint() {
register int x=0;
for(; !isdig(*is); ++is);
for(; isdig(*is); ++is) {
x=x*10+*is-48;
}
return x;
}
inline void putint(int x) {
if(x==0) {
*is++='0';
}
else {
static int s[10], top;
for(top=0; x; x/=10) s[++top]=x%10;
while(top) {
*is++=s[top--]+'0';
}
}
*is++='\n';
}
struct E {
int next, to, id;
}e[N];
inline void add(int x, int y, int id=-1) {
e[++cnt]=(E){ihead[x], y, id}; ihead[x]=cnt;
}
inline void adds(int x, int s) {
for(; x<=tot; x+=x&-x) {
su[x]+=s;
}
}
inline int sum(int x) {
int y=0;
for(; x; x-=x&-x) {
y+=su[x];
}
return y;
}
inline void bfs() {
static int q[N], fr, ta;
fr=ta=0;
q[ta++]=0;
while(fr!=ta) {
int x=q[fr++];
for(int ch=0; ch<26; ++ch) {
if(c[x][ch]) {
int y=c[x][ch];
q[ta++]=y;
if(x==0) {
add(0, y);
continue;
}
fail[y]=c[fail[x]][ch];
add(fail[y], y);
}
else {
c[x][ch]=c[fail[x]][ch];
}
}
}
}
inline void dfs(int x) {
static int fid=0;
FF[x]=++fid;
for(int i=ihead[x]; i; i=e[i].next) {
dfs(e[i].to);
}
LL[x]=fid;
}
inline void getans(int x) {
adds(FF[x], 1);
for(int i=ihead[x]; i; i=e[i].next) {
int y=e[i].to;
ans[e[i].id]=sum(LL[y])-sum(FF[y]-1);
}
for(int ch=0; ch<26; ++ch) {
if(c[x][ch] && (x==0 || c[x][ch]!=c[fail[x]][ch])) {
getans(c[x][ch]);
}
}
adds(FF[x], -1);
}
void init() {
fread(buf, 1, sizeof buf, stdin);
for(; !isok(*is); ++is);
int now=0, n=0, len=0;
for(; isok(*is); ++is) {
if(*is=='P') {
pos[++n]=now;
}
else if(*is=='B') {
now=last[len--];
}
else {
int ch=*is-'a';
if(!c[now][ch]) {
c[now][ch]=++tot;
}
last[++len]=now;
now=c[now][ch];
}
}
bfs();
dfs(0);
}
int main() {
init();
memset(ihead, 0, sizeof(int)*(tot+1));
cnt=0;
int m=getint();
for(int i=0; i<m; ++i) {
int x, y;
x=getint();
y=getint();
add(pos[y], pos[x], i);
}
++tot;
getans(0);
is=buf;
for(int i=0; i<m; ++i) {
putint(ans[i]);
}
fwrite(buf, 1, sizeof(char)*(is-buf), stdout);
return 0;
}
【BZOJ】2434: [Noi2011]阿狸的打字机的更多相关文章
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- bzoj 2434 [Noi2011]阿狸的打字机 AC自动机
[Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4001 Solved: 2198[Submit][Status][D ...
- 【刷题】BZOJ 2434 [Noi2011]阿狸的打字机
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- bzoj 2434 [Noi2011]阿狸的打字机(fail树+离线处理+BIT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题意] 按照一定规则生成n个字符串,回答若干个询问:(x,y),问第x个字符串 ...
- BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题目大意] 给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串 ...
- bzoj 2434 [Noi2011]阿狸的打字机——AC自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2434 dfs AC自动机,走过的点权值+1,回溯的时候权值-1:走到询问的 y 串的节点,看 ...
- bzoj 2434: [Noi2011]阿狸的打字机
#include<cstdio> #include<iostream> #include<cstring> #define M 100008 using names ...
- ●BZOJ 2434: [Noi2011]阿狸的打字机
●赘述题目 (题意就不赘述了) ●解法: ●我先想的一个比较暴力的方法(要TLE): (ac自动机)先求出last数组(参见刘汝佳的解释:last[j]:表示j节点沿着失配指针往回走时,遇到的下一个单 ...
随机推荐
- gbdt可视化
gbdt的最大优点,和决策树一样,高度可解释,最喜欢的分类模型:) #!/usr/bin/env python #coding=gbk # ============================== ...
- Jsonp跨域访问原理和实例
>>什么是跨域 出于安全方面的考虑,页面中的JavaScript无法访问其他服务器上的数据,当前域名的js只能读取同域下的窗口属性,即同源策略.而跨域就是通过某些手段来绕过同源策略限制,实 ...
- OGG异常处理
ALTER REPLICAT LCMA1REP,BEGIN NOW 从最新的trail文件开始读取 ALTER REPLICAT LCMA1REP,EXTSEQNO 191(对应的 trail的序号 ...
- 在Asp.Net MVC中PartialView与EditorFor和DisplayFor的区别
相同之处: PartialView, EditorFor 和 DisplayFor 都可以用作来实现页面的公共部分,其他页面可以根据需求来引用. 不同之处: PartialView 是从Page的角度 ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA/(树链剖分+数据结构) + MST
E. Minimum spanning tree for each edge Connected undirected weighted graph without self-loops and ...
- linux下epoll如何实现高效处理百万句柄的
linux下epoll如何实现高效处理百万句柄的 分类: linux 技术分享 2012-01-06 10:29 4447人阅读 评论(5) 收藏 举报 linuxsocketcachestructl ...
- java学习笔记(3):网络编程
基本原理 客户端要发起通信,首先得知道运行服务器程序主机的IP地址,然后由网络的基础结构利用目标地址,将发送的信息传递到正确的主机上.地址可以是数字型(IPv4或者IPv6),也可以是字符串(必须先被 ...
- redis如何安装
http://www.redis.net.cn/download/ (1)下载,解压,编译: $ wget http://download.redis.io/releases/redis-3.0.6. ...
- opengl纹理映射总结
大概步骤: 1.创建纹理对象,并为他指定一个纹理. 2.确定纹理如何应用到每个像素上. 3.启用纹理贴图 4.绘制场景,提供纹理和几何坐标 过滤:由于我们提供的纹理图像很少能和最终的屏幕坐标形成对应, ...
- Spring的LoadTimeWeaver(代码织入)
在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入.类加载期织入和运行期织入.编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中:而类加载期织入则指通过特 ...