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
aPaPBbP
3
1 2
1 3
2 3
Sample Output
2
1
0
HINT
1<=N<=10^5
1<=M<=10^5
输入总长<=10^5
题解
经典的AC自动机+fail树+dfs序+树状数组,考试中会有点难想到用dfs序,写起来还是爽的飞起的
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <ctime>
#include <set>
using namespace std;
#define rep(i,l,r) for(i=l;i<=r;i++)
#define ser(i,r,l) for(i=r;i>=l;i--)
#define INF 100005
#define inf 100000007
typedef long long ll;
priority_queue<int >QwQ;
int l1,l=0,m,top=1,last=0,tot=1,cnt=0;
int c[INF<<1],to[INF<<1],h[INF<<1],s[INF<<1],p[INF],fa[INF],t[INF][30],q[INF],fail[INF];
int ans[INF],L[INF],R[INF];
char s1[INF];
int read()
{
int k=0,f=1;
char ch;
while(ch<'0' || ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')k=(k<<1)+(k<<3)+ch-'0',ch=getchar();
return k*f;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int v)
{
int i,j,k;
for(i=x;i<=cnt;i+=lowbit(i))c[i]+=v;
}
int getsum(int x)
{
int i,j,k=0;
for(i=x;i;i-=lowbit(i))k+=c[i];
return k;
}
void hah(int x,int y)
{
to[++l]=y,h[l]=s[x],s[x]=l;
}
void Insert()
{
int i,j,k,now=1,id=0;
rep(i,0,l1-1){
if(s1[i]=='P')p[++id]=now;
else if(s1[i]=='B')now=fa[now];
else {
k=s1[i]-'a'+1;
if(!t[now][k])t[now][k]=++tot,fa[tot]=now;
now=t[now][k];
}
}
}
void build_fail()
{
int i,j,k,p;
q[0]=1,fail[1]=0;
while(last<top){
k=q[last++];
rep(i,1,26)
if(t[k][i]){
p=fail[k];
while(!t[p][i])p=fail[p];
fail[t[k][i]]=t[p][i];
q[top++]=t[k][i];
}
}
}
void dfs(int x)
{
int i,j,k;
L[x]=++cnt;
for(i=s[x];i;i=h[i])
dfs(to[i]);
R[x]=++cnt;
}
void solve()
{
int i,j,k,now=1,id=0;
add(L[1],1);
rep(i,0,l1-1){
if(s1[i]=='P'){
id++;
for(j=s[id];j;j=h[j]){
k=p[to[j]];
ans[j]=getsum(R[k])-getsum(L[k]-1);
}
}
else if(s1[i]=='B')add(L[now],-1),now=fa[now];
else now=t[now][s1[i]-'a'+1],add(L[now],1);
}
}
void init()
{
int i,j,k,x,y;
tot=1;
rep(i,1,26)t[0][i]=1;
scanf("%s",s1);
l1=strlen(s1);
Insert();
build_fail();
rep(i,1,tot)hah(fail[i],i);
dfs(0);
l=0;
memset(s,0,sizeof(s));
m=read();
rep(i,1,m){
x=read(),y=read();
hah(y,x);
}
solve();
rep(i,1,m)printf("%d\n",ans[i]);
}
void work()
{
int i,j,k;
}
int main()
{
init();
work();
return 0;
}