2434: [Noi2011]阿狸的打字机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1016 Solved: 572
[ Submit][ Status]
Description
阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。
经阿狸研究发现,这个打字机是这样工作的:
l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
例如,阿狸输入aPaPBbP,纸上被打印的字符如下:
a
aa
ab
我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?
Input
输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。
第二行包含一个整数m,表示询问个数。
接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。
Output
输出m行,其中第i行包含一个整数,表示第i个询问的答案。
Sample Input
3
1 2
1 3
2 3
Sample Output
1
0
HINT
1<=N<=10^5
......这题调了一个晚上。。虽然并不复杂,但写起来各种小错误>_<
先构图建AC自动机,然后把FAIL边倒过来,这样询问I J 就成了查询已I为根的子树中有几个点是J的。。。。
求出FAIL树的DFS序后,I的子树的编号是连续的,所以用树状数组维护就行了。。GG
/*/今天换了个新鼠标,用起来蛮顺的,还送了个很好玩的清洁果冻(像是果冻)。。马上就又要去郑州集训了。。
又要被各种犇虐了,好感动,一年了,现在我已不再那么浮躁了,NOI 2014 加油。 /*/ /*/陈年旧事 /*/
var
i,j,k,tot,num,zs,time,now,p,m,x,y:longint;
c:char;
trie:array [0..500000,'a'..'z'] of longint;
s:ansistring;
a,ans,f,rd,cd,d,fal,z,fa:array [0..1000000] of longint;
b:array [0..1000000,1..3] of longint;
procedure inser(k,x:longint);
var
p:longint;
begin
p:=k;
while p<=length(s)+1 do
begin
inc(f[p],x);
p:=p+p and (-p);
end;
end;
function sum(k:longint):longint;
var
p:longint;
begin
p:=k;
sum:=0;
while p<>0 do
begin
inc(sum,f[p]);
p:=p-p and (-p);
end;
end;
procedure insert(x,y:longint);
begin
inc(num);
b[num,1]:=y;
b[num,2]:=a[x];
a[x]:=num;
end;
procedure insertt(x,y,tob:longint);
begin
inc(num);
b[num,1]:=y;
b[num,2]:=a[x];
b[num,3]:=tob;
a[x]:=num;
end;
procedure dfs(k:longint);
var
p,j:longint;
begin
inc(time);
rd[k]:=time;
p:=a[k];
while p<>0 do
begin
j:=b[p,1];
dfs(j);
p:=b[p,2];
end;
cd[k]:=time;
end;
begin
readln(s);
zs:=1;
for i:=1 to length(s) do
if s[i]='P' then
begin
d[zs]:=tot;
inc(zs);
end
else
if s[i]='B' then now:=fa[now] else
if trie[now,s[i]]<>0 then now:=trie[now,s[i]]
else
begin
inc(tot);
trie[now,s[i]]:=tot;
fa[tot]:=now;
now:=tot;
end;
z[1]:=0;
i:=1;
j:=2;
while (z[i]<>0) or (i=1) do
begin
for c:='a' to 'z' do
if trie[z[i],c]<>0 then
begin
z[j]:=trie[z[i],c];
p:=fal[z[i]];
while (trie[p,c]=0)and(p<>0) do
p:=fal[p];
if z[i]<>0 then fal[z[j]]:=trie[p,c]
else fal[z[j]]:=0;
insert(fal[z[j]],z[j]);
inc(j);
end;
inc(i);
end;
dfs(0);
read(m);
num:=0;
fillchar (a,sizeof(a),0);
fillchar (b,sizeof(b),0);
for i:=1 to m do
begin
read(x,y);
insertt(y,x,i);
end;
zs:=1;
now:=0;
for i:=1 to length(s) do
if s[i]='P' then
begin
p:=a[zs];
while p<>0 do
begin
j:=b[p,1];
if b[p,3]=1 then
write;
ans[b[p,3]]:=sum(cd[d[j]])-sum(rd[d[j]]-1);
p:=b[p,2];
end;
inc(zs);
end
else
if s[i]='B' then
begin
inser(rd[now],-1);
now:=fa[now];
end
else
begin
now:=trie[now,s[i]];
inser(rd[now],1);
end;
for i:=1 to m do
writeln(ans[i]);
end.