简要题意:
给你一个字符串 S S S,请你支持:
- 末尾加字符
- 末尾删字符
- 给一个询问串 Q Q Q ,求 Q Q Q 在 S [ l : r ] S[l:r] S[l:r] 中出现了多少次。
强制在线
题解:
如果第三个操作没有 l , r l,r l,r 的限制就是 BZOJ4768,后缀平衡树裸题。
有的话也没什么区别,开个vector维护一下子树内的点有哪些就行了。
复杂度好像是两个 log,但是跑得飞起。
代码:
#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++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
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;
}
}using namespace IO;
using std::cerr;
using std::cout;
cs int N=2e5+7;
char s[N];int sl;
char q[N];int ql;
int lc[N],rc[N],sz[N],*bad,rt;
double L[N],R[N],rebl,rebr;
std::vector<int> nd[N];
cs double alpha=0.75;
inline double val(int u){if(u==0)return -1e18;return 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));
}
void ins(int &u,int i,double l=0,double r=1e18){
if(!u){
u=i,sz[i]=1;
lc[u]=rc[u]=0;
L[i]=l,R[i]=r;
nd[i].clear();
nd[i].push_back(i);
return ;
}++sz[u];nd[u].push_back(i);
double M=(L[u]+R[u])/2;
if(Cmp(u,i)){
ins(rc[u],i,M,r);
if(sz[rc[u]]>sz[u]*alpha)
bad=&u,rebl=l,rebr=r;
}else {
ins(lc[u],i,l,M);
if(sz[lc[u]]>sz[u]*alpha)
bad=&u,rebl=l,rebr=r;
}
}
void merge(std::vector<int> &res,cs std::vector<int> &b){
cs std::vector<int> a=res;res.resize(a.size()+b.size());
std::merge(a.begin(),a.end(),b.begin(),b.end(),res.begin());
}
int merge(int a,int b){
if(!a||!b)return a|b;
if(sz[a]>sz[b]){
merge(nd[a],nd[b]);
rc[a]=merge(rc[a],b);
sz[a]=sz[lc[a]]+sz[rc[a]]+1;
return a;
}else {
merge(nd[b],nd[a]);
lc[b]=merge(a,lc[b]);
sz[b]=sz[lc[b]]+sz[rc[b]]+1;
return b;
}
}
void del(int &u,int i,double l=0,double r=1e18){
if(u==i){
u=merge(lc[u],rc[u]);
return ;
}--sz[u];
nd[u].pop_back();
double M=(L[u]+R[u])/2;
if(val(u)<val(i)){
del(rc[u],i,M,r);
if(sz[lc[u]]>sz[u]*alpha)
bad=&u,rebl=l,rebr=r;
}else {
del(lc[u],i,l,M);
if(sz[rc[u]]>sz[u]*alpha)
bad=&u,rebl=l,rebr=r;
}
}
int Q[N],qn;
void ino_dfs(int u){
if(lc[u])ino_dfs(lc[u]);
Q[++qn]=u;
if(rc[u])ino_dfs(rc[u]);
}
int build(int l,int r,double vl,double vr){
if(l>r)return 0;
int mid=(l+r)>>1;double vm=(vl+vr)/2;
int u=Q[mid];L[u]=vl,R[u]=vr,sz[u]=r-l+1;
lc[u]=build(l,mid-1,vl,vm);
rc[u]=build(mid+1,r,vm,vr);
nd[u].clear();nd[u].push_back(u);
merge(nd[u],nd[lc[u]]);merge(nd[u],nd[rc[u]]);
return u;
}
void rebuild(int &u){
qn=0;ino_dfs(u);
u=build(1,qn,rebl,rebr);
}
void Ins(int i){
bad=nullptr;ins(rt,i);
if(bad!=nullptr)
rebuild(*bad);
}
void Del(int i){
bad=nullptr;del(rt,i);
if(bad!=nullptr)
rebuild(*bad);
}
int query(cs std::vector<int> &nd,int l,int r){
return std::upper_bound(nd.begin(),nd.end(),r)
-std::lower_bound(nd.begin(),nd.end(),l);
}
int Rank(int l,int r){
int u=rt,ans=0;
while(u){
int tp=0;
for(int re j=0;j<=ql;++j)
if(q[j]!=s[u-j]){
tp=q[j]>s[u-j];
break;
}
if(tp)ans+=query(nd[lc[u]],l,r)+(l<=u&&u<=r);
u=tp?rc[u]:lc[u];
}return ans;
}
int las;
inline int toid(char c){
return islower(c)?c-'a':26+c-'A';
}
inline char toch(int id){
return id>25?id-26+'A':id+'a';
}
void decode(){
for(int re i=0;i<ql;++i)
q[i]=toch((toid(q[i])+las)%52);
}
void Main(){
sl=get_s(s+1);
for(int re i=1;i<=sl;++i)Ins(i);
int Q=gi();
while(Q--)switch(gi()){
case 1:{
ql=get_s(q);
decode();
s[++sl]=q[0];
Ins(sl);
break;
}case 2:{
Del(sl--);
break;
}case 3:{
int l=gi(),r=gi();ql=get_s(q);
decode();l^=las,r^=las;
std::reverse(q,q+ql);
if(r-l+1<ql)cout<<(las=0)<<"\n";
else {
l+=ql-1;
int ans=-Rank(l,r);
q[ql]=127;ans+=Rank(l,r);
cout<<(las=ans)<<"\n";
}
break;
}
}
}
inline void file(){
#ifdef zxyoi
freopen("fantasy.in","r",stdin);
#else
freopen("fantasy.in","r",stdin);
freopen("fantasy.out","w",stdout);
#endif
}signed main(){file();Main();return 0;}