bzoj 2434 fail tree+dfs序
首先比较明显的是我们可以将字符串组建立ac自动机,那么对于询问s1字符串在s2字符串中出现的次数,就是在以s1结尾为根的fail tree中,子树有多少个节点是s2的节点,这样我们处理fail tree的dfs序,然后用BIT维护,但是如果只是在线处理询问的话会tle,因为每个询问需要将节点的每一位在BIT中都修改,那么我们就浪费了好多性质,因为对于好多字符串拥有较长的LCP,那么我们可以模拟建trie的过程在自动机上跑,每遇到一个添加的字符,就解决所有询问为某字符串在该字符串中出现的次数,这样就可以了。
/**************************************************************
Problem: 2434
User: BLADEVIL
Language: C++
Result: Accepted
Time:852 ms
Memory:39128 kb
****************************************************************/
//By BLADEVIL
#include <cstdio>
#include <cstring>
#define maxn 200010
using namespace std;
struct node{
int cnt,last,left,right;
node *child[],*fail,*father;
node(){
cnt=last=left=right=;
fail=father=NULL;
memset(child,,sizeof child);
}
}nodepool[maxn],*totnode,*root,*que[maxn],*adr[maxn],*other[maxn],*adrans[maxn];
char c[maxn];
int len,tot,l,sum;
int pre[maxn],bit[maxn];
int ll,preans[maxn],otherans[maxn],lastans[maxn],sizeans[maxn];
int ans[maxn];
void add(int x,int y){
while (x<=sum){
bit[x]+=y;
x+=x&(-x);
}
}
int ask(int x){
int ans=;
while (x){
ans+=bit[x];
x-=x&(-x);
}
return ans;
}
void connect(node *x,node *y){
pre[++l]=x->last;
x->last=l;
other[l]=y;
//printf("%d %d\n",x,y);
}
void connectans(int x,int y,int z){
preans[++l]=lastans[x];
lastans[x]=l;
otherans[l]=y;
sizeans[l]=z;
}
void build_trie(){
totnode=nodepool; root=totnode++;
scanf("%s",&c); len=strlen(c);
node *t=root;
for (int i=;i<len;i++){
if (c[i]=='P') adrans[++tot]=t; else
if (c[i]=='B') t=t->father; else {
if (!t->child[c[i]-'a'])
t->child[c[i]-'a']=totnode++,t->child[c[i]-'a']->father=t;
t=t->child[c[i]-'a'];
adr[i]=t;
};
//printf("%d ",t);
}
//printf("\n");
//for (int i=0;i<len;i++) printf("%d ",adr[i]);
//for (node *i=nodepool;i!=totnode;i++) printf("%d %d\n",i,i->father);
}
void build_ac(){
int h=,t=;
que[]=root; root->fail=root;
for (int i=;i<;i++) if (!root->child[i]) root->child[i]=root;
while (h<t){
node *v=que[++h];
for (int i=;i<;i++) if (v->child[i]&&v->child[i]!=root){
que[++t]=v->child[i];
node *u=v->fail;
que[t]->fail=u->child[i]!=que[t]?u->child[i]:root;
} else v->child[i]=v->fail->child[i];
}
//for (int i=1;i<=t;i++) printf("%d %d ",que[i],que[i]->fail); printf("\n");
//for (int i=1;i<=tot;i++) printf("%d ",adr[i]); printf("\n");
}
void dfs(node *x,node *fa){
//printf("%d %d %d\n",x,fa,sum);
x->left=++sum;
for (int p=x->last;p;p=pre[p]){
if (other[p]==fa) continue;
dfs(other[p],x);
}
x->right=sum;
}
/*void work(){
for (node *i=nodepool;i!=totnode;i++) if (i!=root) connect(i->fail,i);
dfs(root,NULL);
//for (node *i=nodepool;i!=totnode;i++) printf("%d %d %d %d\n",i,i->left,i->right,i->father);
int m;
scanf("%d",&m);
while (m--){
int x,y;
scanf("%d %d",&x,&y);
for (node *i=adr[y];i!=root;i=i->father) add(i->left,1);//printf("%d ",i->left);
//printf("%d %d",adr[x]->left,adr[x]->right);
//printf("%d ",ask(adr[x]->right));
printf("%d\n",ask(adr[x]->right)-ask(adr[x]->left-1));
for (node *i=adr[y];i!=root;i=i->father) add(i->left,-1);
}
}*/
void work(){
for (node *i=nodepool;i!=totnode;i++) if (i!=root) connect(i->fail,i);
dfs(root,NULL);
int m;
scanf("%d",&m);
for (int i=;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
connectans(y,x,i);
}
int stack[maxn],tot=,ansy=;
memset(stack,,sizeof stack);
for (int i=;i<len;i++){
if (c[i]=='P'){
ansy++;
for (int p=lastans[ansy];p;p=preans[p]){
ans[sizeans[p]]=ask(adrans[otherans[p]]->right)-ask(adrans[otherans[p]]->left-);
}
} else
if (c[i]=='B') {
add(adr[stack[tot--]]->left,-);
} else {
stack[++tot]=i;
add(adr[i]->left,);
}
}
for (int i=;i<=m;i++) printf("%d\n",ans[i]);
}
int main(){
build_trie();
build_ac();
work();
return ;
}
bzoj 2434 fail tree+dfs序的更多相关文章
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树
Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...
- bzoj2434 fail树 + dfs序 + 树状数组
https://www.lydsy.com/JudgeOnline/problem.php?id=2434 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...
- 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组
E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- NOI2011阿狸的打字机(fail树+DFS序)
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- poj 3321 Apple Tree dfs序+线段树
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Description There is an apple tree outsid ...
- [poj3321]Apple Tree(dfs序+树状数组)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 26762 Accepted: 7947 Descr ...
- Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组
C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...
随机推荐
- Hive整体优化策略
一 整体架构优化 现在hive的整体框架如下,计算引擎不仅仅支持Map/Reduce,并且还支持Tez.Spark等.根据不同的计算引擎又可以使用不同的资源调度和存储系统. 整体架构优化点: 1 根据 ...
- 个人github blog环境设置
每个人都想拥有自己的网站,但是大部分比较屌丝,不想花钱租赁服务器,哈哈,屌丝有屌丝办法.github应该都听说过吧,github.io提供了此功能,而且使用github来管理自己的代码,如果你有域名, ...
- C#之WCF入门1—简单的wcf例子
第一步:创建一个空的解决方案,新建一个WCF服务应用程序项目(使用默认名字) 来模拟服务端,新建一个控制台应用程序项目(名称改为 ConsoleApp)来模拟客户端. 第二步:简单分析WcfServi ...
- 3ds Max学习日记(二)
搞了一天终于把第二章弄完了,虽然有点慢,但也是没有办法,毕竟中途学累了总得放松一下吧. 又get到了一个新知识点,是关于3ds max的捕捉工具的,详情见3DS MAX 学习笔记 一(捕捉工具 ...
- 再看RCU
从昨天晚上开始,我就立志要把RCU拿下,昨晚加今天早上看了RCU的东西,太细节的原理我就不扣了,放弃,知道RCU是怎么用的就可以了,赶紧看文件系统中dcache的管理了. 说说RCU,RCU其实是很简 ...
- [C/C++] C++抽象类
转自:http://www.cnblogs.com/dongsheng/p/3343939.html 一.纯虚函数定义 纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己 ...
- 第51天:封装可视区域大小函数client
一.client 可视区域 offsetWidth: width + padding + border (披着羊皮的狼) clientWidth: width + ...
- BZOJ3167/BZOJ4824 HEOI2013SAO/CQOI2017老C的键盘(树形dp)
前者是后者各方面的强化版. 容易想到设f[i][j]表示i子树中第j小的是i的方案数(即只考虑相对关系).比较麻烦的在于转移.考虑逐个合并子树.容易想到枚举根原来的排名和子树根原来的排名,算一发组合数 ...
- 虚拟机如何设置U盘启动项
开始配置虚拟机时选"自定义"不要选"典型",在“SCSI设配器”选LSI logic ,(不是默认的那个):然后其他正常默认创建,虚拟机建好后,再添加U盘为虚拟 ...
- 【题解】51nod 1686第K大区间
成功的秘诀,在于克服自己看题解的冲动……[笑哭].自己A掉这题还是灰常开心的~ 以及爱死 two - pointer ! two - pointer 大法是真的好哇……这个题目有上一题的经验:求第\( ...