NC15050. 真的字符串
描述
给你一个字符串init,要求你支持三个操作
1.在当前字符串的后面插入若干个字符
2.在当前字符串的后面删除若干个字符
3.询问字符串s在当前字符串中出现了几次?(作为连续子串)
输入描述
第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行:
ADD str表示在后面插入str这个字符串
DEL x表示在后面删除x个字符
QUERY str表示询问str在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0
读入串str之后,
使用这个过程将之解码成真正询问的串TrueStr
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result
插入的时候,将TrueStr插到当前字符串后面即可。
ADD和QUERY操作的字符串都需要解压
输出描述
对于每个询问,输出一行一个数表示答案
示例1
输入:
3 A QUERY B ADD BBABBBBAAB DEL 1
输出:
0
C++11(clang++ 3.9) 解法, 执行用时: 1245ms, 内存消耗: 177120K, 提交时间: 2020-06-11 09:06:53
#include<bits/stdc++.h> #define Tp template<typename Ty> #define Ts template<typename Ty,typename... Ar> #define Reg register #define RI Reg int #define Con const #define CI Con int& #define I inline #define W while #define N 800000 #define Q 3000000 using namespace std; int n,fg;char op[10],s[Q+5]; class LinkCutTree { private: #define PU(x) (O[x].Sz=O[x].ISz+O[O[x].S[0]].Sz+O[O[x].S[1]].Sz+O[x].T) #define IR(x) (O[O[x].F].S[0]^x&&O[O[x].F].S[1]^x) #define Wh(x) (O[O[x].F].S[1]==x) #define Co(x,y,d) (O[O[x].F=y].S[d]=x) #define PD(x) O[x].R&&(Re(O[x].S[0]),Re(O[x].S[1]),O[x].R=0) #define Re(x) (swap(O[x].S[0],O[x].S[1]),O[x].R^=1) #define MR(x) (Ac(x),S(x),Re(x)) int St[N<<1];struct node {int T,Sz,ISz,R,F,S[2];}O[N<<1]; I void Ro(RI x) { RI f=O[x].F,p=O[f].F,d=Wh(x);!IR(f)&&(O[p].S[Wh(f)]=x), O[x].F=p,Co(O[x].S[d^1],f,d),Co(f,x,d^1),PU(f),PU(x); } I void S(RI x) { RI f=x,T=0;W(St[++T]=f,!IR(f)) f=O[f].F;W(T) PD(St[T]),--T; W(!IR(x)) f=O[x].F,!IR(f)&&(Ro(Wh(x)^Wh(f)?x:f),0),Ro(x); } I void Ac(RI x) { for(RI y=0;x;x=O[y=x].F) S(x), O[x].ISz+=O[O[x].S[1]].Sz-O[y].Sz,O[x].S[1]=y,PU(x); } public: I void Init(CI x) {O[x].Sz=O[x].T=1;} I void Link(CI x,CI y) {MR(x),MR(y),O[O[y].F=x].ISz+=O[y].Sz,O[x].Sz+=O[y].Sz;} I void Cut(CI x,CI y) {MR(x),Ac(y),S(x),O[x].Sz-=O[y].Sz,O[x].S[1]=O[y].F=0;} I void Del(CI x) {MR(x),O[x].T=0,--O[x].Sz;} I int Qry(CI f,CI x) {return MR(f),Ac(x),S(f),O[x].Sz;} }LCT; class SuffixAutomation { private: int Nt,lst,T,S[N+5];struct node {int L,F,S[30];}O[N<<1]; public: I SuffixAutomation() {S[T=1]=Nt=lst=1;} I void Ins(CI x) { RI p=lst,now=lst=++Nt;O[S[++T]=now].L=O[p].L+1,LCT.Init(now); W(p&&!O[p].S[x]) O[p].S[x]=now,p=O[p].F;if(!p) return LCT.Link(O[now].F=1,now); RI q=O[p].S[x];if(O[p].L+1==O[q].L) return LCT.Link(O[now].F=q,now); RI k=++Nt;(O[k]=O[q]).L=O[p].L+1,O[now].F=O[q].F=k, LCT.Cut(O[k].F,q),LCT.Link(O[k].F,k),LCT.Link(k,now),LCT.Link(k,q); W(p&&O[p].S[x]==q) O[p].S[x]=k,p=O[p].F; } I int Qry(char *s) { RI p=1;for(RI i=1;i<=n;++i) if(!(p=O[p].S[s[i]&31])) return 0; return LCT.Qry(O[p].F,p); } I void Del(CI t) {T-=t,lst=fg?0:S[T];for(RI i=1;i<=t;++i) LCT.Del(S[T+i]);} }S; I void T(char *s,RI p) {for(RI i=1;i<=n;++i) swap(s[i],s[(p=(p*131+i-1)%n)+1]);} int main() { RI Qt,i;for(scanf("%d%s",&Qt,s+1),n=strlen(s+1),i=1;i<=n;++i) S.Ins(s[i]&31); RI t,p=0;fg=Qt<=50000;W(Qt--) switch(scanf("%s",op),op[0]) { case 'Q':scanf("%s",s+1),n=strlen(s+1),T(s,p),printf("%d\n",t=S.Qry(s)),p^=t;break; case 'A':scanf("%s",s+1),n=strlen(s+1),T(s,p);for(i=1;i<=n;++i) S.Ins(s[i]&31);break; case 'D':scanf("%d",&t),S.Del(t);break; }return 0; }
C++14(g++5.4) 解法, 执行用时: 982ms, 内存消耗: 12552K, 提交时间: 2019-07-12 16:19:03
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; int gi(){ int x=0,w=1;char ch=getchar(); while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if (ch=='-') w=0,ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return w?x:-x; } const int N = 3e6+5; const double Alpha = 0.7; int mask,n,q,l,rt,tot,ls[N],rs[N],sz[N],s[N],top,ans; char str[N],opt[10],que[N];double a[N]; void dfs(int &x){ if (!x) return; dfs(ls[x]);s[++top]=x;dfs(rs[x]);x=0; } void build(int &x,int L,int R,double l,double r){ if (L>R) {x=0;return;} int MID=L+R>>1;double mid=(l+r)/2.0; a[x=s[MID]]=mid;sz[x]=R-L+1; build(ls[x],L,MID-1,l,mid); build(rs[x],MID+1,R,mid,r); } void rebuild(int &x,double l,double r){ top=0;dfs(x);build(x,1,top,l,r); } void insert(int &x,int y,double l,double r,int f){ double mid=(l+r)/2.0; if (!x) {x=y,ls[x]=rs[x]=0,a[x]=mid,sz[x]=1;return;} int fg=f;++sz[x]; if (str[y]<str[x]||(str[y]==str[x]&&a[y-1]<a[x-1])){ fg|=(Alpha*sz[x]<=sz[ls[x]]+1); insert(ls[x],y,l,a[x],fg); }else{ fg|=(Alpha*sz[x]<=sz[rs[x]]+1); insert(rs[x],y,a[x],r,fg); } if (fg&&!f) rebuild(x,l,r); } #define upt(x) sz[x]=sz[ls[x]]+sz[rs[x]]+1 void merge(int x,int y,int &p){ if (!x||!y) {p=x|y;return;} if (sz[x]>sz[y]) merge(rs[x],y,rs[x]),upt(x),p=x; else merge(x,ls[y],ls[y]),upt(y),p=y; } void del(int &x,int y){ if (x^y) --sz[x],del(a[y]<a[x]?ls[x]:rs[x],y); else merge(ls[x],rs[x],x); } void readin(){ scanf("%s",que);l=strlen(que); for (int i=0,tmp=mask;i<l;++i) tmp=(tmp*131+i)%l,swap(que[i],que[tmp]); } int query(int x){ if (!x) return 0;int c=0; for (int i=0;i<=l;++i) if (que[i]^str[x-i]) {c=que[i]>str[x-i];break;} return c?sz[ls[x]]+1+query(rs[x]):query(ls[x]); } int main(){ // freopen("1.in","r",stdin); // freopen("zsy.out","w",stdout); q=gi();scanf("%s",str+1);n=strlen(str+1); for (int i=1;i<=n;++i) insert(rt,i,0,1e9,0); while (q--){ scanf("%s",opt); if (opt[0]=='Q'){ readin();reverse(que,que+l); ans=-query(rt);que[l]='Z'+1;ans+=query(rt); printf("%d\n",ans);mask^=ans; } if (opt[0]=='A'){ readin(); for (int i=1;i<=l;++i) str[n+i]=que[i-1],insert(rt,n+i,0,1e9,0); n+=l; } if (opt[0]=='D'){ l=gi();n-=l; for (int i=1;i<=l;++i) del(rt,n+i); } } return 0; }