[JSOI2008]火星人
阿新 • • 發佈:2021-08-31
Description
初始一個串 \(S\),有兩種操作。
- 在某個位置增/刪一個字元。
- 詢問兩個字尾的最長公共字首。
Solution
一開始以為是什麼高階東西…… SAM 並不能處理在中間插入字元的情況,所以應該直接排除了。觀察到“最長”這個東西是有單調性的,所以可以考慮二分,然後就轉換成兩個子串相不相同。可以用雜湊來處理。對於修改的話,用平衡樹維護一下區間雜湊即可。
#include<stdio.h> #include<algorithm> #include<string.h> #include<stdlib.h> using namespace std; typedef long long ll; inline int read(){ int x=0,flag=1; char c=getchar(); while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();} return flag? x:-x; } const int Bs=233; const int Mod=998244353; const int N=1e5+7; struct Node{ int ls,rs,sz,key,val; ll Hs; }t[N]; ll pw[N]; int rt=0; char s[N]; inline int New(char c){ static int tot=0; int p=++tot; t[p]=(Node){0,0,1,rand(),c,c}; return p; } #define lid t[id].ls #define rid t[id].rs void update(int id){ t[id].sz=t[lid].sz+t[rid].sz+1; t[id].Hs=(t[lid].Hs+pw[t[lid].sz]*(t[id].val+t[rid].Hs*Bs%Mod)%Mod)%Mod; } int merge(int x,int y){ if(!x||!y) return x+y; if(t[x].key<t[y].key){ t[x].rs=merge(t[x].rs,y); return update(x),x; }else{ t[y].ls=merge(x,t[y].ls); return update(y),y; } } void split(int id,int k,int &x,int &y){ if(!id) x=y=0; else{ if(t[lid].sz+1<=k) x=id,split(rid,k-t[lid].sz-1,rid,y); else y=id,split(lid,k,x,lid); update(id); } } int query(int l,int r){ int x,y,z; split(rt,r,y,z); split(y,l-1,x,y); int ret=t[y].Hs; rt=merge(merge(x,y),z); return ret; } int main(){ srand(114514); pw[0]=1; for(int i=1;i<N;i++) pw[i]=pw[i-1]*Bs%Mod; scanf("%s",s+1); int m=strlen(s+1); for(int i=1;i<=m;i++) rt=merge(rt,New(s[i])); int Q=read(); char op[3]; while(Q--){ scanf("%s",op); if(op[0]=='Q'){ int x=read(),y=read(); if(x>y) swap(x,y); int l=1,r=t[rt].sz-y+1,ans=0; while(l<=r){ int mid=(l+r)>>1; if(query(x,x+mid-1)==query(y,y+mid-1)) l=mid+1,ans=mid; else r=mid-1; } printf("%d\n",ans); }else if(op[0]=='R'){ int x=read(); char y[2]; scanf("%s",y); int a,b,c; split(rt,x,b,c); split(b,x-1,a,b); t[b].val=t[b].Hs=y[0]; rt=merge(merge(a,b),c); }else{ int x=read(); char y[2]; scanf("%s",y); int a,b; split(rt,x,a,b); rt=merge(merge(a,New(y[0])),b); } } }