[JSOI2008]火星人
题目大意:
给定一个只包含小写英文字母的字符串$s$,进行以下3种操作共$m(m\leq150000)$次:
1.改变某个位置上的字符;
2.在某个位置插入一个字符;
3.求两个后缀的LCS长度。
保证操作过程中串长不超过$100000$。
思路:
Splay维护字符串及对应区间的Hash值,询问时二分答案即可。
细节:
不卡哈希不代表底数可以取偶数。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 #include<algorithm> 5 typedef unsigned long long uint64; 6 inline int getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^'0'; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 11 return x; 12 } 13 inline char getalpha() { 14 register char ch; 15 while(!isalpha(ch=getchar())); 16 return ch; 17 } 18 const int N=100003,BASE=27; 19 char s[N]; 20 int n; 21 class SplayTree { 22 private: 23 int val[N],size[N],par[N],ch[N][2],root; 24 uint64 hash[N],pow[N]; 25 int id(const char &c) const { 26 return c-'a'; 27 } 28 int sz,new_node(const int &x) { 29 size[++sz]=1; 30 val[sz]=x; 31 return sz; 32 } 33 void push_up(const int &p) { 34 size[p]=size[ch[p][0]]+size[ch[p][1]]+1; 35 hash[p]=hash[ch[p][0]]+val[p]*pow[size[ch[p][0]]]+hash[ch[p][1]]*pow[size[ch[p][0]]+1]; 36 } 37 void rotate(const int &x) { 38 const int y=par[x],z=par[y]; 39 const bool b=x==ch[y][0]; 40 par[ch[x][b]=par[ch[y][!b]=ch[x][b]]=y]=x; 41 par[ch[z][y==ch[z][1]]=x]=z; 42 push_up(y),push_up(x); 43 } 44 void splay(int x,const int &goal) { 45 for(register int y=par[x],z=par[y];y!=goal;rotate(x),z=par[y=par[x]]) { 46 if(z!=goal) rotate((x==ch[y][0])^(y==ch[z][0])?x:y); 47 } 48 if(!goal) root=x; 49 } 50 int find(int x) { 51 for(register int y=root;;y=ch[y][size[ch[y][0]]+1<x]) { 52 if(y!=root&&y==ch[par[y]][1]) x-=size[ch[par[y]][0]]+1; 53 if(size[ch[y][0]]+1==x) return y; 54 } 55 } 56 uint64 calc(const int &l,const int &r) { 57 splay(find(l),0); 58 splay(find(r+2),root); 59 return hash[ch[ch[root][1]][0]]; 60 } 61 public: 62 void build() { 63 for(register int i=pow[0]=1;i<N;i++) { 64 pow[i]=pow[i-1]*BASE; 65 } 66 for(register int i=ch[0][1]=1;i<=n;i++) { 67 par[ch[i][1]=i+1]=i; 68 val[i+1]=id(s[i]); 69 } 70 par[sz=ch[n+1][1]=n+2]=n+1; 71 size[n+2]=1; 72 splay(n+2,0); 73 } 74 int query(const int &x,const int &y) { 75 int l=0,r=sz-std::max(x,y)-1; 76 while(l<=r) { 77 const int mid=(l+r)>>1; 78 if(calc(x,x+mid-1)==calc(y,y+mid-1)) { 79 l=mid+1; 80 } else { 81 r=mid-1; 82 } 83 } 84 return l-1; 85 } 86 void modify(const int &x,const char &c) { 87 splay(find(x),0); 88 splay(find(x+2),root); 89 val[ch[ch[root][1]][0]]=id(c); 90 splay(ch[ch[root][1]][0],0); 91 } 92 void insert(const int &x,const char &c) { 93 splay(find(x+1),0); 94 splay(find(x+2),root); 95 par[ch[ch[root][1]][0]=new_node(id(c))]=ch[root][1]; 96 splay(ch[ch[root][1]][0],0); 97 } 98 }; 99 SplayTree t; 100 int main() { 101 scanf("%s",&s[1]); 102 n=strlen(&s[1]); 103 t.build(); 104 for(register int i=getint();i;i--) { 105 const int opt=getalpha(),x=getint(); 106 if(opt=='Q') printf("%d\n",t.query(x,getint())); 107 if(opt=='R') t.modify(x,getalpha()); 108 if(opt=='I') t.insert(x,getalpha()); 109 } 110 return 0; 111 }