一开始一直被题面误导(人傻)。。一看要插入想到了splay但是没想到hash啊。。做法就是用splay维护这个字串,每个节点存一个字符,就和维护数列一样搞就行了。。查询的时候二分公共前缀长度,然后转出区间比较hash值就行了。。维护hash的时候要注意,一种方法是让它乘的去不取模,第二种是模一个大质数,事实证明第一种更快,第二种要开long long,运算过程不能爆范围,要不然是会出错的。。
#include<iostream>
#include<cstdio>
#include<memory.h>
#include<cstring>
#define p 9875321
#define maxn 1000005
#define ll long long
using namespace std;
char ch[10],s[maxn];
int i,m,n,x,y,root=0,nd=0,c[maxn][2],size[maxn],h[maxn],pre[maxn],d[maxn],v[maxn];
void newnode(int &x,int fa,int k)
{
x=++nd;pre[x]=fa;
size[x]=1;
c[x][0]=c[x][1]=0;
h[x]=v[x]=k;
}
void update(int x)
{
size[x]=size[c[x][0]]+size[c[x][1]]+1;
// h[x]=((h[c[x][0]]+(ll)v[x]*(ll)d[size[c[x][0]]])%p+(ll)h[c[x][1]]*(ll)d[size[c[x][0]]+1]%p)%p;
h[x]=h[c[x][0]]+v[x]*d[size[c[x][0]]]+h[c[x][1]]*d[size[c[x][0]]+1];
}
void rot(int x,int kind)
{
int y=pre[x],z=pre[y];
c[y][!kind]=c[x][kind];pre[c[x][kind]]=y;
c[x][kind]=y;pre[y]=x;
pre[x]=z;if (z) c[z][c[z][1]==y]=x;
update(y);update(x);
}
void splay(int x,int goal)
{
int y,z,kind;
while (pre[x]!=goal)
{
y=pre[x];
if (pre[y]==goal) rot(x,c[y][0]==x);
else
{
z=pre[y];kind=c[z][0]==y;
if (c[y][kind]==x) rot(x,!kind);else rot(y,kind);
rot(x,kind);
}
}
if (goal==0) root=x;
}
void build(int &x,int fa,int l,int r)
{
if (l>r) return;
int mid=(l+r)/2;
newnode(x,fa,s[mid]-'a');
build(c[x][0],x,l,mid-1);build(c[x][1],x,mid+1,r);
update(x);
}
int findkth(int x,int k)
{
if (size[c[x][0]]>=k) return findkth(c[x][0],k);
if (k==size[c[x][0]]+1) return x;
return findkth(c[x][1],k-size[c[x][0]]-1);
}
void ins(int pos,int val)
{
int x=findkth(root,pos+1),y=findkth(root,pos+2);
splay(x,0);splay(y,x);
newnode(c[y][0],y,val);
update(y);update(x);n++;
}
void change(int pos,int val)
{
int x=findkth(root,pos+1);
splay(x,0);
v[x]=val;update(x);
}
int hash(int pos,int len)
{
int x=findkth(root,pos),y=findkth(root,pos+len+1);
splay(x,0);splay(y,x);
return (h[c[y][0]]);
}
int query(int s1,int s2)
{
int l=1,r=min(n-s1+1,n-s2+1),mid,ans=0;
while (l<=r)
{
mid=(l+r)/2;
if (hash(s1,mid)==hash(s2,mid)) ans=mid,l=mid+1;else r=mid-1;
}
return ans;
}
int main()
{
freopen("1014.in","r",stdin);
freopen("1014.out","w",stdout);
scanf("%s",s+1);
n=strlen(s+1);d[0]=1;h[0]=0;
for (i=1;i<=maxn-1;i++) d[i]=d[i-1]*27;
newnode(root,0,1);newnode(c[root][1],root,1);
build(c[c[root][1]][0],c[root][1],1,n);
update(c[root][1]);update(root);
scanf("%d\n",&m);
for (i=1;i<=m;i++)
{
scanf("%s%d",ch,&x);
switch (ch[0])
{
case 'Q':scanf("%d",&y);printf("%d\n",query(x,y));break;
case 'R':scanf("%s",ch);change(x,ch[0]-'a');break;
case 'I':scanf("%s",ch);ins(x,ch[0]-'a');break;
}
scanf("\n");
}
}