洛谷P2414 [NOI2011]阿狸的打字机(AC自动机)
考虑一下,如果串B在串A中出现过,那么A的fail指针必定直接或间接指向B
那么我们可以把fail树建起来,那么就变成B代表的节点的子树里有多少节点属于A
然后这就是一个序列统计问题,直接用dfs序+树状数组可以维护
具体的操作就是,先把每一个点有关的询问给存起来,然后等到在trie树上一遍dfs,当dfs到这个串的结束节点说明所有有关这个串的节点都被遍历到(可以在遍历的时候顺便用树状数组维护序列和),然后对每一个询问查一下子树和即可
//minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=;
int tot=;
struct node{
int num,type;
node(){}
node(int num,int type):num(num),type(type){}
};
queue<node> q;
int ch[N][],End[N],word,fa[N],fail[N],dis[N];
inline int insert(int p,int c){
if(ch[p][c]) return ch[p][c];
ch[p][c]=++tot,fa[tot]=p;return tot;
}
inline int back(int p){return fa[p];}
inline void ed(int p){End[p]=++word,dis[word]=p;}
void build(){
for(int i=;i<;++i)
if(ch[][i])
q.push(node(ch[][i],i)),fail[ch[][i]]=;
while(!q.empty()){
node now=q.front();q.pop();
if(fail[now.num]!=){
int trail=fail[fa[now.num]];
while(true){
if(ch[trail][now.type]){trail=ch[trail][now.type];break;}
if(trail==) break;trail=fail[trail];
}
fail[now.num]=trail;
}
for(int i=;i<;++i)
if(ch[now.num][i])
q.push(node(ch[now.num][i],i));
}
}
int ver[N<<],Next[N<<],head[N],E=;
inline void add(int u,int v){
ver[++E]=v,Next[E]=head[u],head[u]=E;
}
int ver1[N],Next1[N],head1[N],edge1[N],E1=;
inline void add1(int u,int v,int num){
ver1[++E1]=v,Next1[E1]=head1[u],head1[u]=E1,edge1[E1]=num;
}
int c[N<<];
inline void addd(int x,int y){
for(;x<=tot;x+=x&-x) c[x]+=y;
}
inline int sum(int x){
int res=;
for(;x;x-=x&-x) res+=c[x];
return res;
}
int dfn[N],sz[N],cnt=,ans[N];
bool book[N];
void dfsfail(int u){
dfn[u]=++cnt,sz[u]=,book[u]=true;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(!book[v]) dfsfail(v),sz[u]+=sz[v];
}
}
void dfstrie(int u){
addd(dfn[u],);
if(End[u]){
for(int i=head1[End[u]];i;i=Next1[i]){
int v=ver1[i],x=dis[v];
// printf("%d %d %d\n",v,x,edge1[i]);
ans[edge1[i]]=sum(dfn[x]+sz[x]-)-sum(dfn[x]-);
}
}
for(int i=;i<;++i)
if(ch[u][i]) dfstrie(ch[u][i]);
addd(dfn[u],-);
}
char s[N];int len,m,st;
int main(){
// freopen("testdata.in","r",stdin);
scanf("%s",s+);
len=strlen(s+);
for(st=;st<=len;++st)
if(s[st]!='B'&&s[st]!='P') break;
int p=insert(,s[st]-'a');
for(int i=st+;i<=len;++i){
if(s[i]=='B') p=back(p);
else if(s[i]=='P') ed(p);
else p=insert(p,s[i]-'a');
}
scanf("%d",&m);
for(int i=,u,v;i<=m;++i){
scanf("%d%d",&u,&v);
add1(v,u,i);
}
build();
for(int i=;i<=tot;++i)
add(fail[i],i),add(i,fail[i]);
dfsfail(),dfstrie();
for(int i=;i<=m;++i) printf("%d\n",ans[i]);
return ;
}
洛谷P2414 [NOI2011]阿狸的打字机(AC自动机)的更多相关文章
- 洛谷 P2414 [NOI2011]阿狸的打字机 解题报告
P2414 [NOI2011]阿狸的打字机 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母 ...
- 洛谷P2414 - [NOI2011]阿狸的打字机
Portal Description 首先给出一个只包含小写字母和'B'.'P'的操作序列\(s_0(|s_0|\leq10^5)\).初始时我们有一个空串\(t\),依次按\(s_0\)的每一位进行 ...
- 【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解
这一题是对AC自动机的充分理解和树dfs序的巧妙运用. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和' ...
- BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 我写的是离线做法,不知道有没有在线做法. 转化一波题意,\(x\)在AC ...
- P2414 [NOI2011]阿狸的打字机 AC自动机
题意 给定n个模式串,有m个询问,每次询问第X个模式串在第Y个模中出现了多少次 解题思路 以fail树相反的方向建一棵树T,问题转化为X的子树中有多少个y的终止节点.跑出T的dfs序,X的子树就可以表 ...
- 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序+树状 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组
[NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...
随机推荐
- SDUT OJ类型转换函数的应用
题目描述 处理一个复数与一个double数相加的运算,结果存放在一个double型变量d1中,输出d1的值.定义Complex(复数)类,在成员函数中包含重载类型转换运算符:operator doub ...
- 世界各国Google网址大全
http://www.oschina.net/question/100896_50293 冰岛 https://www.google.is/ 丹麦 https://www.google.dk/ 挪威 ...
- jquery 3D分页翻转滑块
jquery 3D分页翻转滑块,jquery分页,jquery插件,jquery,3D翻转,css3分页,360度旋转,网页特效代码3D分页翻转滑块是一款使用网格样式与滑块效果分页的特效.
- Android Studio 代码混淆(你真的会混淆吗)
一.前言 今天要打包新产品,突然忘了混淆的参数是怎么写的了,虽然之前也混淆过,可是具体配置的参数代码有些记不起来了,因此决定花点时间写篇博客记录一下,方便以后查找和自己的记忆. 二.Android S ...
- php设计模式课程---9、桥接模式是什么
php设计模式课程---9.桥接模式是什么 一.总结 一句话总结: 一个类没干完,另外一个类接着给它干完 实质是类的拼接,也就是用类的组合代替了类的继承,因为类的组合可以有很多种方式,所以桥接就是类的 ...
- spring2.5整合struts2
首先第一步: 导入jar包: 我的做法: 导入你的基本使用的spring的jar包 和基本使用的struts2的jar包 然后struts2中有一个和spring整合的jar包一定要导入,不然会抛异常 ...
- 第六章-jQuery
jQuery的理念是: 写更少的代码, 完成更多的工作 jQuery有两个版本1.x和2.x, 版本2.x不再支持IE678 jQuery最明显的标志就是$, jQuery把所有的功能都封装在了jQu ...
- Ubuntu16.04上安装arm-linux-gcc4.4.3
一.首先下载arm-linux-gcc-4.4.3.tar.gz安装包,安装包地址: http://www.cr173.com/soft/42654.html 二.解压安装包: sudo tar -z ...
- 注意!!一定要谨慎使用c/c++原生指针
使用指针,要非常小心,今天在做一个小游戏时,就碰到一个使用原生指针的问题,找了好几个小时,才定位到问题的所在,晕. 主要是顶层逻辑中引用了一个指针,而在业务逻辑中将此指针删除了.这种在代码量很少的情况 ...
- 【Python】File IO
1.numpy.genfromtxt() numpy.genfromtxt() CSV文件很容易被numpy类库的genfromtxt方法解析 2.