splay维护区间内的hash值+二分答案。。。
一开始脑残跑去维护各个前缀的hash值。。结果发现修改的时候没法打懒标记(也可能是我太弱不会)
跑去看黄学长题解发现直接维护区间内的hash值就可以了。。而且挺容易合并的TAT(其实挺显然的,都用splay了为啥还不维护区间的hash值。。。)
然后就变水题了= =而且这题数据弱可以直接自然溢出。。。。当然就算这样我的splay还是一如既往的慢TAT
每次查询的时候二分lcp长度就好了。
时间复杂度O(nlog²n)。。。还有一个巨大的常数因子233
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define ll unsigned long long 5 using namespace std; 6 const int maxn=100033; 7 ll hash[maxn],jc[maxn]; 8 int ch[maxn][2],size[maxn],fa[maxn],num[maxn]; 9 int i,j,n,m,x,y,rt,tot; 10 char s[maxn]; 11 int ra;char rx; 12 inline int read(){ 13 rx=getchar();ra=0; 14 while(rx<'0'||rx>'9')rx=getchar(); 15 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 16 } 17 inline void upd(int x){ 18 int l=ch[x][0],r=ch[x][1]; 19 size[x]=size[l]+1+size[r]; 20 hash[x]=hash[l]*jc[size[x]-size[l]]+num[x]*jc[size[r]]+hash[r]; 21 } 22 inline void rotate(int x,int &rt){ 23 int f=fa[x],gfa=fa[f]; 24 if(f==rt)rt=x;else ch[gfa][ch[gfa][1]==f]=x; 25 int l=ch[f][1]==x,r=l^1; 26 fa[x]=gfa,fa[f]=x,ch[f][l]=ch[x][r],ch[x][r]=f,fa[ch[f][l]]=f; 27 upd(f),upd(x); 28 } 29 void splay(int x,int &rt){ 30 int f,gfa; 31 while(x!=rt){ 32 f=fa[x],gfa=fa[f]; 33 if(f!=rt)rotate(((ch[f][0]==x)^(ch[gfa][0]==f))?x:f,rt); 34 rotate(x,rt); 35 } 36 } 37 int find(int x,int k){ 38 int l=ch[x][0]; 39 if(size[l]>=k)return find(l,k); 40 else if(size[l]+1==k)return x; 41 else return find(ch[x][1],k-size[l]-1); 42 } 43 void change(int now,char c){ 44 int x=find(rt,now);splay(x,rt); 45 int y=find(rt,now+1);splay(y,ch[x][1]); 46 hash[y]+=(ll)(c-'a'+13-num[y])*jc[size[y]-1]; 47 num[y]=c-'a'+13,upd(x); 48 } 49 void ins(int now,char c){ 50 int x=find(rt,now+1);splay(x,rt); 51 int y=find(rt,now+2),z;splay(y,ch[x][1]); 52 ch[y][0]=z=++tot;num[z]=c-'a'+13,fa[z]=y,size[z]=1,hash[z]=num[z]; 53 upd(y),upd(x); 54 } 55 void build(int l,int r,int premid){ 56 if(l>r)return; 57 int mid=(l+r)>>1; 58 fa[mid]=premid,ch[premid][premid<mid]=mid; 59 if(mid>1&&mid<n+2)num[mid]=s[mid-2]-'a'+13;else num[mid]=0; 60 if(l<r)build(l,mid-1,mid),build(mid+1,r,mid),upd(mid); 61 else size[mid]=1,hash[mid]=num[mid]; 62 } 63 inline ll gethash(int l,int r){ 64 l=find(rt,l),splay(l,rt); 65 r=find(rt,r+2),splay(r,ch[l][1]); 66 return hash[ch[r][0]]; 67 } 68 inline int query(int a,int b){ 69 if(a>b)swap(a,b);if(num[find(rt,a+1)]!=num[find(rt,b+1)])return 0; 70 splay(b+1,rt); 71 if(gethash(a,a+n-b)==gethash(b,n))return n-b+1; 72 int l,r,mid; 73 l=1,r=n-b; 74 while(l<r){ 75 mid=(l+r+1)>>1; 76 if(gethash(a,a+mid-1)==gethash(b,b+mid-1))l=mid;else r=mid-1; 77 } 78 return l; 79 } 80 int main(){ 81 scanf("%s",s);n=strlen(s); 82 for(i=jc[0]=1;i<=n+2;i++)jc[i]=jc[i-1]*197; 83 rt=(n+2+1)>>1;tot=n+2;build(1,n+2,0); 84 m=read();char id,z; 85 while(m--){ 86 for(id=getchar();id<'A'||id>'Z';id=getchar()); 87 x=read(); 88 if(id=='Q')y=read(),printf("%d\n",query(x,y)); 89 if(id=='R'){ 90 for(z=getchar();z<'a'||z>'z';z=getchar()); 91 change(x,z); 92 } 93 if(id=='I'){ 94 for(z=getchar();z<'a'||z>'z';z=getchar()); 95 jc[tot+1]=jc[tot]*197;ins(x,z);n++; 96 } 97 } 98 return 0; 99 }