传送门
题解:
后缀平衡树练手题。
设询问串为 q q q, q q q#为在 q q q后面接了一个极大字符的串,如果我们能够求得后缀数组,显然排名在 q q q和 q q q#之间的就是 q q q能够匹配的位置。
由于强制在线,维护后缀数组用后缀平衡树即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int get_s(char *s){
int len=0;char c;
while(isspace(c=gc()));
while(s[len++]=c,!isspace(c=gc())&&c!=EOF);
return s[len]='\0',len;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int N=3e6+7;
int m;
char s[N];int sl;
char q[N];int ql;
namespace SGT{
cs int N=8e5+7;
int lc[N],rc[N],siz[N],rt,*bad;
double L[N],R[N];cs double alpha=0.7;
inline double val(int u){return u==0?-1e18:(L[u]+R[u]);}
inline bool Cmp(int u,int v){
return s[u]<s[v]||(s[u]==s[v]&&val(u-1)<val(v-1));
}
inline void ins(int &u,int i,double l=0,double r=1e18){
if(!u){u=i,siz[i]=1,L[i]=l,R[i]=r;return ;}
++siz[u];double mid=(l+r)*0.5;
if(Cmp(u,i)){
ins(rc[u],i,mid,r);
if(siz[rc[u]]>siz[u]*alpha)bad=&u;
}
else {
ins(lc[u],i,l,mid);
if(siz[lc[u]]>siz[u]*alpha)bad=&u;
}
}
int q[N],qn;
void inorder_dfs(int u){
if(lc[u])inorder_dfs(lc[u]);q[++qn]=u;
if(rc[u])inorder_dfs(rc[u]);
}
inline int build(int l,int r,double vl,double vr){
if(l>r)return 0;int mid=l+r>>1;double Mid=(vl+vr)*0.5;
int u=q[mid];L[u]=vl,R[u]=vr;siz[u]=r-l+1;
lc[u]=build(l,mid-1,vl,Mid);
rc[u]=build(mid+1,r,Mid,vr);
return u;
}
inline void rebuild(int &u){
qn=0;inorder_dfs(u);
u=build(1,qn,L[u],R[u]);
}
inline void Ins(int i){
bad=NULL;ins(rt,i);
if(bad!=NULL)rebuild(*bad);
}
inline int Rank(char *q,int l){
int u=rt,ans=0;
while(u){
int tp=0;
for(int re j=0;j<=l;++j)
if(q[j]!=s[u-j]){tp=q[j]>s[u-j];break;}
if(tp)ans+=siz[lc[u]]+1;
u=tp?rc[u]:lc[u];
}
return ans;
}
}
int msk;
void decode(char *s,int l){
for(int re i=0,tp=msk;i<l;++i)
std::swap(s[i],s[tp=(tp*131+i)%l]);
}
signed main(){
#ifdef zxyoi
freopen("substring.in","r",stdin);
#endif
m=gi();sl=get_s(s+1);
for(int re i=1;i<=sl;++i)SGT::Ins(i);
while(m--){
ql=get_s(q);
switch(q[0]){
case 'A':{
ql=get_s(q+1);decode(q+1,ql);
for(int re i=1;i<=ql;++i)
s[sl+i]=q[i],SGT::Ins(sl+i);sl+=ql;
break;
}
case 'Q':{
ql=get_s(q);decode(q,ql);
std::reverse(q,q+ql);
int ans=-SGT::Rank(q,ql);
q[ql]=127;ans+=SGT::Rank(q,ql);
cout<<ans<<"\n";msk^=ans;
break;
}
}
}
return 0;
}