阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和‘B‘、‘P‘两个字母。
经阿狸研究发现,这个打字机是这样工作的:
l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
l 按一下印有‘B‘的按键,打字机凹槽中最后一个字母会消失。
l 按一下印有‘P‘的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
例如,阿狸输入aPaPBbP,纸上被打印的字符如下:
a
aa
ab
我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?
输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。
第二行包含一个整数m,表示询问个数。
接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。
输出m行,其中第i行包含一个整数,表示第i个询问的答案。
1 #include<iostream>
2 #include<cstdio>
3 #include<algorithm>
4 #include<cstring>
5 #include<queue>
6 #include<vector>
7 #define LL long long
8 using namespace std;
9 const int mxn=100010;
10 int read(){
11 int x=0,f=1;char ch=getchar();
12 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
13 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
14 return x*f;
15 }
16 struct edge{int v,nxt;}e[mxn<<1];
17 int hd[mxn],mct=0;
18 void add_edge(int u,int v){
19 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
20 }
21 vector<int>ask[mxn];//询问
22 vector<int>id[mxn];
23 int ans[mxn];
24 //
25 int n,m;
26 char s[mxn];
27 int ind[mxn],outd[mxn],sz=0;
28 int tr[mxn<<1];
29 void add(int x,int v){while(x<=sz){tr[x]+=v;x+=x&-x;}}
30 int smm(int x){
31 int res=0;
32 while(x){res+=tr[x];x-=x&-x;}
33 return res;
34 }
35 int pos[mxn],sct=0;
36 struct Aca{
37 int t[mxn][26],fail[mxn];
38 int fa[mxn];
39 int rt,cnt;
40 void clear(){cnt=1;rt=1;for(int i=0;i<26;i++)t[0][i]=1;}
41 void insert(char s[]){
42 int now=rt;
43 int len=strlen(s);
44 for(int i=0;i<len;i++){
45 if(s[i]==‘P‘){pos[++sct]=now;continue;}
46 else if(s[i]==‘B‘){now=fa[now];continue;}
47 if(!t[now][s[i]-‘a‘]){
48 t[now][s[i]-‘a‘]=++cnt;
49 fa[t[now][s[i]-‘a‘]]=now;
50 }
51 now=t[now][s[i]-‘a‘];
52 }
53 }
54 void Build(){
55 queue<int>q;
56 q.push(rt);
57 fail[1]=0;
58 while(!q.empty()){
59 int now=q.front();q.pop();
60 for(int i=0;i<26;i++){
61 if(t[now][i]){
62 int k=fail[now];
63 while(!t[k][i])k=fail[k];
64 fail[t[now][i]]=t[k][i];
65 q.push(t[now][i]);
66 }
67 }
68 }
69 }
70 }aca;
71 void DFS(int u){
72 ind[u]=++sz;
73 for(int i=hd[u];i;i=e[i].nxt){
74 DFS(e[i].v);
75 }
76 outd[u]=++sz;
77 return;
78 }
79 int main()
80 {
81 int i,j,u,v;
82 scanf("%s",s);
83 n=strlen(s);
84 aca.clear();
85 aca.insert(s);
86 aca.Build();
87 for(int i=aca.rt;i<=aca.cnt;i++){
88 add_edge(aca.fail[i],i);
89 }
90 DFS(0);
91 m=read();
92 for(i=1;i<=m;i++){
93 u=read();v=read();
94 ask[v].push_back(u);
95 id[v].push_back(i);
96 }
97 int now=aca.rt;int t=0;
98 //
99 add(ind[1],1);//add(outd[1],-1);
100 for(i=0;i<n;i++){
101 // printf("now: %c \n",s[i]);
102 if(s[i]==‘P‘){
103 t++;
104 u=t;
105 for(j=0;j<ask[u].size();j++){
106 v=pos[ask[u][j]];
107 // printf("%d to %d\n",ind[v],outd[v]);
108 // printf("%d %d\n",smm(outd[v]),smm(ind[v]-1));
109 ans[id[u][j]]=smm(outd[v])-smm(ind[v]-1);
110 }
111 continue;
112 }
113 else if(s[i]==‘B‘){
114 add(ind[now],-1);//add(outd[now],1);
115 now=aca.fa[now];continue;
116 }
117 now=aca.t[now][s[i]-‘a‘];
118 add(ind[now],1);//add(outd[now],-1);
119 }
120 //
121 for(i=1;i<=m;i++)printf("%d\n",ans[i]);
122 return 0;
123 }