传送门
题意:
有一个打字机,有三种操作:
- 打一个小写字母
- 删去最近打的一个小写字母
- 将打印当前的字符串
现在多组询问,每次问第
x
x
x个被打印串在第
y
y
y个被打印串中出现次数。
思路:
按照题意先建出
t
r
i
e
trie
trie树与
f
a
i
l
fail
fail树。
然后考虑第
x
x
x个打印串在第
y
y
y个被打印串中出现次数等于
f
a
i
l
fail
fail树上面
x
x
x子树中属于字符串
y
y
y的节点数。
于是我们离线排序+
d
f
s
dfs
dfs序+
b
i
t
bit
bit维护即可。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
typedef pair<int,int> pii;
const int N=2e5+5;
char s[N];
int cnt=0,n,m;
vector<pii>qry[N];
int ans[N];
namespace Bit{
int bit[N];
inline int lowbit(const int&x){return x&-x;}
inline void update(int p,const int&v){for(;p<=cnt;p+=lowbit(p))bit[p]+=v;}
inline int query(int p){int ret=0;for(;p;p^=lowbit(p))ret+=bit[p];return ret;}
}
namespace acam{
int son[N][26],rt=1,tot=1,in[N],fail[N],out[N],fa[N],ed[N];
vector<int>e[N];
void dfs(int p){
in[p]=++cnt;
for(ri i=0;i<e[p].size();++i)dfs(e[p][i]);
out[p]=cnt;
}
inline void getfail(){
static int q[N],hd,tl;
hd=1,tl=0;
for(ri i=0;i<26;++i)if(son[rt][i])q[++tl]=son[rt][i],fail[son[rt][i]]=rt;
while(hd<=tl){
int p=q[hd++];
e[fail[p]].push_back(p);
for(ri i=0;i<26;++i){
if(!son[p][i]){son[p][i]=son[fail[p]][i];continue;}
fail[son[p][i]]=son[fail[p]][i]?son[fail[p]][i]:rt,q[++tl]=son[p][i];
}
}
}
inline void build(){
for(ri p=1,i=1,up=strlen(s+1),x;i<=up;++i){
if(s[i]>='a'&&s[i]<='z'){
if(!son[p][x=s[i]-'a'])son[p][x]=++tot,fa[tot]=p;
p=son[p][x];
}
if(s[i]=='B')p=fa[p];
if(s[i]=='P')ed[++n]=p;
}
getfail();
dfs(rt);
}
inline int query(int p){return Bit::query(out[ed[p]])-Bit::query(in[ed[p]]-1);}
inline void solve(){
for(ri p=1,i=1,nn=0,up=strlen(s+1),x;i<=up;++i){
if(s[i]>='a'&&s[i]<='z'){
p=son[p][s[i]-'a'];
Bit::update(in[p],1);
}
if(s[i]=='B')Bit::update(in[p],-1),p=fa[p];
if(s[i]=='P'){
++nn;
for(ri j=0;j<qry[nn].size();++j)ans[qry[nn][j].se]=query(qry[nn][j].fi);
}
}
}
}
int main(){
scanf("%s",s+1);
acam::build();
m=read();
for(ri x,y,i=1;i<=m;++i)x=read(),y=read(),qry[y].push_back(pii(x,i));
acam::solve();
for(ri i=1;i<=m;++i)cout<<ans[i]<<'\n';
return 0;
}