[JSOI2008]火星人

题目大意:
   给定一个只包含小写英文字母的字符串$s$,进行以下3种操作共$m(mleq150000)$次:
    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
",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 }
原文地址:https://www.cnblogs.com/skylee03/p/8522469.html