题意:

1<=N<=10^5

1<=M<=10^5
输入总长<=10^5
 
思路:

From http://blog.csdn.net/lych_cys/article/details/50646799

首先你会发现他打字的方式非常奇妙。。实际上不就是在构建一颗Tire吗?P相当于给节点标记;B相当于退回父亲节点;a..z相当于建立新的节点。

然后跑AC自动机得到fail指针。

首先得知道如何得出单个操作x,y。在后缀数组(sam,后缀树等)中,判断u是v的子串的方法是看是否是每一个后缀的前缀;而AC自动机则架构在前缀树Tire上,自然地,判断AC自动机上面的两个子串u,v(AC自动机上的子串x可以看成是从根节点到节点x连成的一个字符串),u是否是v的子串,就等价于u是否是v某个前缀的后缀!在AC自动机上,判断u是x的后缀非常简单,只要看x能否沿着fail指针走到u即可。

那么,查询u在v中出现了几次就比较明了了,只要看从根节点到v的路径中有多少个x,满足u是x的后缀即x能沿着fail指针走到u。

于是,我们可以将fail[x]作为x(这里的x不同于上面的x)的父节点建立一颗新的树,这样的话如果i是j的祖先,那么j显然可以由fail指针走到i。那么查询u,v时,将root->v的路径上的每一个点都变为1,那么答案就相当于u的子树中有多少个1了。

但是这样直接在线查询显然不行(除非写一些高大上的数据结构)。单点修改子树查询可以用dfs序+树状数组解决,因此关键是减少修改次数。我们可以离线,以v为关键字排序,这样就可以根据原来建立AC自动机的顺序进行修改了,只要在进入一个点t时+1,出去时-1,查询时自然root->v的路径上的每一个点都是1了。

var map:array[..,..]of longint;
f,fa,ind,oud,q,t,x,y,id,head,vet,next,ans,num:array[..]of longint;
n,m,i,cnt,now,tot,j,k,len,time,u,que,tmp:longint;
ch:ansistring; procedure acauto;
var t,w,u,p,i,son:longint;
begin
t:=; w:=; q[]:=;
while t<w do
begin
inc(t); u:=q[t];
for i:= to do
if map[u,i]> then
begin
son:=map[u,i];
p:=f[u];
if u= then f[son]:=
else f[son]:=map[p,i];
inc(w); q[w]:=son;
end
else
begin
p:=f[u];
if u= then map[u,i]:=
else map[u,i]:=map[p,i];
end;
end;
end; procedure add(a,b:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
head[a]:=tot;
end; procedure dfs(u:longint);
var e,v:longint;
begin
inc(time); ind[u]:=time; oud[u]:=time;
e:=head[u];
while e<> do
begin
v:=vet[e];
if ind[v]= then
begin
dfs(v);
oud[u]:=oud[v];
end;
e:=next[e];
end;
end; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure qsort(l,r:longint);
var i,j,t,mid:longint;
begin
i:=l; j:=r; mid:=y[(l+r)>>];
repeat
while mid>y[i] do inc(i);
while mid<y[j] do dec(j);
if i<=j then
begin
swap(x[i],x[j]);
swap(y[i],y[j]);
swap(id[i],id[j]);
inc(i); dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end; function lowbit(x:longint):longint;
begin
exit(x and (-x));
end; procedure ins(x,y:longint);
begin
while x<=time do
begin
t[x]:=t[x]+y;
x:=x+lowbit(x);
end;
end; function query(x:longint):longint;
begin
query:=;
while x> do
begin
query:=query+t[x];
x:=x-lowbit(x);
end;
end; begin
assign(input,'bzoj2434.in'); reset(input);
assign(output,'bzoj2434.out'); rewrite(output);
readln(ch);
m:=length(ch); len:=; cnt:=; now:=;
for i:= to m do
begin
case ch[i] of
'P':
begin
inc(n); num[n]:=now;
continue;
end;
'B':
begin
now:=fa[now];
continue;
end;
end;
u:=ord(ch[i])-ord('a')+;
if map[now,u]= then
begin
inc(cnt); map[now,u]:=cnt;
fa[cnt]:=now;
end;
now:=map[now,u];
end; acauto;
for i:= to cnt do add(f[i],i);
dfs();
readln(que);
for i:= to que do
begin
read(x[i],y[i]);
id[i]:=i;
end;
qsort(,que);
j:=; k:=; now:=;
for i:= to m do
begin
case ch[i] of
'B':
begin
ins(ind[now],-); now:=fa[now];
continue;
end;
'P':
begin
inc(j);
while (k<=que)and(y[k]=j) do
begin
tmp:=num[x[k]];
ans[id[k]]:=query(oud[tmp])-query(ind[tmp]-);
inc(k);
end;
continue;
end;
end;
now:=map[now,ord(ch[i])-ord('a')+];
ins(ind[now],);
end;
for i:= to que do writeln(ans[i]);
close(input);
close(output);
end.

【BZOJ2434】阿狸的打字机(fail树,DFS序)的更多相关文章

  1. [NOI2011][bzoj2434] 阿狸的打字机 [AC自动机+dfs序+fail树+树状数组]

    题面 传送门 正文 最暴力的 最暴力的方法:把所有询问代表的字符串跑一遍kmp然后输出 稍微优化一下:把所有询问保存起来,把模板串相同的合并,求出next然后匹配 但是这两种方法本质没有区别,都是暴力 ...

  2. NOI 2011 阿狸的打字机 (AC自动机+dfs序+树状数组)

    题目大意:略(太长了不好描述) 良心LOJ传送门 先对所有被打印的字符串建一颗Trie树 观察数据范围,并不能每次打印都从头到尾暴力建树,而是每遍历到一个字符就在Trie上插入这个字符,然后记录每次打 ...

  3. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  4. 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2022  Solved: 1158[Submit][Sta ...

  5. BZOJ2434: [Noi2011]阿狸的打字机(fail树+dfs序)

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  6. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

    [BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...

  7. NOI2011阿狸的打字机(fail树+DFS序)

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  8. BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组

    题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...

  9. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  10. bzoj2434 fail树 + dfs序 + 树状数组

    https://www.lydsy.com/JudgeOnline/problem.php?id=2434 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...

随机推荐

  1. python自动化测试学习笔记-9python的日志模块

    参考 logging模块,用来处理python中的日志: import logging logging.debug('debug')logging.info('info')logging.warnin ...

  2. [笔试面试题] 10-C和C++区别相关

    1 C和C++有什么不同? 机制不同:C是面向过程的(但C也可以编写面向对象的程序):C++是面向对象的,提供了类.但是,C++编写面向对象的程序比C容易. 适用领域不同:C适合要求代码体积小的,效率 ...

  3. hdu6195 cable cable cable

    cable cable cable Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  4. 二分搜索 HDOJ 2289 Cup

    题目传送门 /* 二分搜索:枚举高度,计算体积与给出的比较. */ #include <cstdio> #include <algorithm> #include <cs ...

  5. 自定义View(10)*onSizeChanged,onMeasure,onDraw的注意事项及正确写法

    1,onSizeChanged 触发: 当view的第一次分配大小或以后大小改变时的产生的事件. 工作: 计算绘制内容的位置,面积等相关值.避免每次在onDraw中计算了. 注意: 计算时不要忘记pa ...

  6. 数据传递-------ajaxJson------spring3mvc中使用ajax传json中文乱码解决

    参考来源:http://blog.csdn.net/dangerous_fire/article/details/25904225 第一种解决方法,适用所有情况 因为在controller中返回jso ...

  7. 数据传递-------@RequestParam

    package com.wh.handler; /** * @RequestParam是传递参数的. * @RequestParam用于将请求参数区数据映射到功能处理方法的参数上. * * publi ...

  8. node-rsa加密,java解密调试

    用NODE RSA JS 加密解密正常,用JAVA RSAUtils工具类加密解密正常.但是用node加密玩的java解密不了.原因:node默认的是 DEFAULT_ENCRYPTION_SCHEM ...

  9. 6.12---bug

  10. ES6 学习笔记 - let和const

    let 和 const 命令 学习资料:ECMAScript 6 入门 let 所声明的变量,只在let命令所在的代码块内有效.用途:循环计数器. 如果使用var,只有一个全局变量i: var a = ...