zoukankan      html  css  js  c++  java
  • [bzoj1014](JSOI2008)火星人 prefix (Splay维护哈希)

    Description

    火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。 比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,如果求出了LCQ函数 的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地 说,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此复杂的问题中,火星人是否还能够做到很快地求 取LCQ函数的值。

    Input

    第一行给出初始的字符串。第二行 是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操作有3种,如下所示: 1、 询问。语法:Q x y,x, y均为正整数。功能:计算LCQ(x, y) 限制:1 <= x, y <= 当前字符串长度。 2、 修改。语法:R x d,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字符串长度。 3、 插入:语法:I x d,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x = 0,则在字符串开头插入。限制:x不超过当前字符串长度。

    Output

    对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。

    Sample Input

    madamimadam
    7
    Q 1 7
    Q 4 8
    Q 10 11
    R 3 a
    Q 1 7
    I 10 a
    Q 2 11

    Sample Output

    5
    1
    0
    2
    1

    HINT

    数据规模:

    对于100%的数据,满足:

    1、 所有字符串自始至终都只有小写字母构成。

    2、 M <= 150,000

    3、 字符串长度L自始至终都满足L <= 100,000

    4、 询问操作的个数不超过10,000个。

    对于第1,2个数据,字符串长度自始至终都不超过1,000

    对于第3,4,5个数据,没有插入操作。

    分析

        读着前几行,我一直以为这是道后缀数据结构的模板题,结果地球人却整天想着给我出个大难题,把我批判一番

    ╮(╯▽╰)╭

        由于插入操作在尾部,而查询固定在了两个后缀的首位,我们没有办法利用后缀数据结构同时满足高效插入和高效查询。这时我们可以考虑更易于动态维护的最长公共前缀查询方法——字符串哈希。一个哈希值就相当于一个多项式,我们可以用一个splay tree维护整个序列,其中每个子树的根节点维护子树对应的子串的哈希值。合并的时候,我们只需计算$(leftchild.h * x + value)*x^{rightchild.size} + rightchild.h$作为根节点的信息就可以了。查询的时候,我们可以二分答案,每次在splay树上查询两段的哈希值是否相等。当然,我们知道字符串哈希都有一定的错误概率,保险起见我们可以用不同的素数作为x的取值维护多个哈希值→_→当然如果用的是自然溢出的话这样可能都是白搭……只要拿来个大素数当模数,世界就会更美好= =

      1 /**************************************************************
      2     Problem: 1014
      3     User: AsmDef
      4     Language: C++
      5     Result: Accepted
      6     Time:8932 ms
      7     Memory:7664 kb
      8 ****************************************************************/
      9  
     10 #include <cctype>
     11 #include <cstdio>
     12 #include <cmath>
     13 #include <iostream>
     14 #include <ctime>
     15 #include <cstdlib>
     16 using namespace std;
     17 template<typename T>inline void getd(T &x){
     18     char c = getchar();
     19     bool minus = 0;
     20     while(!isdigit(c) && c != '-')c = getchar();
     21     if(c == '-')minus = 1, c = getchar();
     22     x = c - '0';
     23     while(isdigit(c = getchar()))x = x * 10 - '0' + c;
     24     if(minus)x = -x;
     25 }
     26 /*========================================================*/
     27 typedef unsigned long long ull;
     28 const int maxn = 100005;
     29 const ull p1 = 3127, p2 = 49999, p3 = 2147483647;
     30 char tmp[maxn];
     31 ull pow1[maxn], pow2[maxn], pow3[maxn];
     32 int M;
     33 struct Splay{
     34     int size, val;
     35     ull h1, h2, h3;
     36     Splay* init(int);
     37     Splay *son[2];
     38     int cmp(int k){
     39         if(k <= son[0]->size)return 0;
     40         if(k - son[0]->size == 1)return -1;
     41         return 1;
     42     }
     43     void update(){
     44         size = son[0]->size + son[1]->size + 1;
     45         h1 = son[0]->h1 + pow1[son[0]->size]*(p1 * son[1]->h1 + val);
     46         h2 = son[0]->h2 + pow2[son[0]->size]*(p2 * son[1]->h2 + val);
     47         h3 = son[0]->h3 + pow3[son[0]->size]*(p3 * son[1]->h3 + val);
     48     }
     49 }Nil, *Root, Pool[maxn];
     50 int iter = 0;
     51 Splay* Splay::init(int v){
     52     val = h1 = h2 = h3 = v;
     53     size = 1;
     54     son[0] = son[1] = &Nil;
     55     return this;
     56 }
     57 inline void rot(Splay* &o, bool lr){
     58     Splay *t = o->son[lr];o->son[lr] = t->son[lr^1];t->son[lr^1] = o;o->update();o = t;o->update();
     59 }
     60 inline void find(Splay* &o, int k){
     61     int c = o->cmp(k);
     62     if(c == -1)return;
     63     if(c)k -= o->son[0]->size + 1;
     64     int c2 = o->son[c]->cmp(k), k2 = k;
     65     if(~c2){
     66         if(c2)k2 -= o->son[c]->son[0]->size + 1;
     67         find(o->son[c]->son[c2], k2);
     68         if(c == c2)rot(o, c);
     69         else rot(o->son[c], c2);
     70     }
     71     rot(o, c);
     72 }
     73 inline Splay *newT(char *str, int len){
     74     if(len == 1){return Pool[iter++].init(*str - 'a');}
     75     int mid = len >> 1;
     76     Splay *t = Pool[iter++].init(str[mid] - 'a');
     77     t->son[0] = newT(str, mid);
     78     if(len - mid > 1)t->son[1] = newT(str + mid + 1, len - mid - 1);
     79     t->update();
     80     return t;
     81 }
     82 inline void init(){
     83     Nil.h1 = Nil.h2 = Nil.h3 = Nil.val = Nil.size = 0;
     84     int len = 1, i;
     85     while(!isalpha(*tmp = getchar()));
     86     while(isalpha(tmp[len] = getchar()))++len;
     87     getd(M);
     88     const int m = min(M + len, maxn - 1);
     89     *pow1 = *pow2 = *pow3 = 1;
     90     for(i = 1;i <= m;++i)
     91         pow1[i] = pow1[i-1]*p1, pow2[i] = pow2[i-1]*p2, pow3[i] = pow3[i-1]*p3;
     92     Root = newT(tmp, len);
     93 }
     94 inline bool check(int x, int y, int len){
     95     Splay *t;
     96     ull h11, h12, h13, h21, h22, h23;
     97     if(x == 1){
     98         find(Root, len + 1);
     99         t = Root->son[0];
    100     }
    101     else{
    102         find(Root, x - 1);
    103         find(Root->son[1], len + 1);
    104         t = Root->son[1]->son[0];
    105     }
    106     h11 = t->h1, h12 = t->h2, h13 = t->h3;
    107      
    108     find(Root, y - 1);
    109     if(len == Root->son[1]->size)t = Root->son[1];
    110     else{
    111         find(Root->son[1], len + 1);
    112         t = Root->son[1]->son[0];
    113     }
    114     h21 = t->h1, h22 = t->h2, h23 = t->h3;
    115     if((h11 != h21) || (h12 != h22) || (h13 != h23))return 0;
    116     return 1;
    117 }
    118 inline void Query(){
    119     int l = 1, r, x, y, mid;
    120     getd(x), getd(y);
    121     if(x > y)x ^= y ^= x ^= y;
    122     r = Root->size - y + 1;
    123     if(x == y){
    124         printf("%d", r);
    125         if(M)putchar(' ');
    126         return;
    127     }
    128     while(l <= r){
    129         mid = (l + r) >> 1;
    130         if(check(x, y, mid))l = mid + 1;
    131         else r = mid - 1;
    132     }
    133     printf("%d", r);
    134     if(M)putchar(' ');
    135 }
    136 inline void Change(){
    137     int x, d;
    138     getd(x);while(!isalpha(d = getchar()));d -= 'a';
    139     find(Root, x);
    140     Root->val = d;
    141     Root->update();
    142 }
    143 inline void Insert(){
    144     int x, d;
    145     getd(x);while(!isalpha(d = getchar()));
    146     Splay *t = Pool[iter++].init(d - 'a');
    147     if(!x){
    148         t->son[1] = Root;
    149         Root = t;
    150         Root->update();
    151         return;
    152     }
    153     find(Root, x);
    154     t->son[1] = Root->son[1];Root->son[1] = t;
    155     t->update(); Root->update();
    156 }
    157 int main(){
    158     #if defined DEBUG
    159     freopen("test""r", stdin);
    160     freopen("out.txt""w", stdout);
    161     #else
    162     //freopen("bzoj_1014.in", "r", stdin);
    163     //freopen("bzoj_1014.out", "w", stdout);
    164     #endif
    165     int opt;
    166     init();
    167     while(M--){
    168         while(!isalpha(opt = getchar()));
    169         if(opt == 'Q'){
    170             Query();
    171         }
    172         else if(opt == 'R')Change();
    173         else Insert();
    174     }
    175     #if defined DEBUG
    176     //cout << endl<< (double)clock() / CLOCKS_PER_SEC << " sec" << endl;
    177     #endif
    178     return 0;
    179 }
    180 
    Splay Tree维护字符串哈希(三哈希,自然溢出)
      1 /**************************************************************
      2     Problem: 1014
      3     User: AsmDef
      4     Language: C++
      5     Result: Accepted
      6     Time:4528 ms
      7     Memory:4520 kb
      8 ****************************************************************/
      9  
     10 #include <cctype>
     11 #include <cstdio>
     12 #include <iostream>
     13 #include <ctime>
     14 #include <cstdlib>
     15 using namespace std;
     16 template<typename T>inline void getd(T &x){
     17     char c = getchar();
     18     bool minus = 0;
     19     while(!isdigit(c) && c != '-')c = getchar();
     20     if(c == '-')minus = 1, c = getchar();
     21     x = c - '0';
     22     while(isdigit(c = getchar()))x = x * 10 - '0' + c;
     23     if(minus)x = -x;
     24 }
     25 /*========================================================*/
     26 typedef unsigned long long ull;
     27 const int maxn = 100005;
     28 const ull p3 = 3127, p1 = 49999, p2 = 2147483647;
     29 char tmp[maxn];
     30 ull pow1[maxn];
     31 int M;
     32 struct Splay{
     33     int size, val;
     34     ull h1;
     35     Splay* init(int);
     36     Splay *son[2];
     37     int cmp(int k){
     38         if(k <= son[0]->size)return 0;
     39         if(k - son[0]->size == 1)return -1;
     40         return 1;
     41     }
     42     void update(){
     43         size = son[0]->size + son[1]->size + 1;
     44         h1 = son[0]->h1 + pow1[son[0]->size]*(p1 * son[1]->h1 + val);
     45     }
     46 }Nil, *Root, Pool[maxn];
     47 int iter = 0;
     48 Splay* Splay::init(int v){
     49     val = h1 = v;
     50     size = 1;
     51     son[0] = son[1] = &Nil;
     52     return this;
     53 }
     54 inline void rot(Splay* &o, bool lr){
     55     Splay *t = o->son[lr];o->son[lr] = t->son[lr^1];t->son[lr^1] = o;o->update();o = t;o->update();
     56 }
     57 inline void find(Splay* &o, int k){
     58     int c = o->cmp(k);
     59     if(c == -1)return;
     60     if(c)k -= o->son[0]->size + 1;
     61     int c2 = o->son[c]->cmp(k), k2 = k;
     62     if(~c2){
     63         if(c2)k2 -= o->son[c]->son[0]->size + 1;
     64         find(o->son[c]->son[c2], k2);
     65         if(c == c2)rot(o, c);
     66         else rot(o->son[c], c2);
     67     }
     68     rot(o, c);
     69 }
     70 inline Splay *newT(char *str, int len){
     71     if(len == 1){return Pool[iter++].init(*str - 'a');}
     72     int mid = len >> 1;
     73     Splay *t = Pool[iter++].init(str[mid] - 'a');
     74     t->son[0] = newT(str, mid);
     75     if(len - mid > 1)t->son[1] = newT(str + mid + 1, len - mid - 1);
     76     t->update();
     77     return t;
     78 }
     79 inline void init(){
     80     Nil.h1 = Nil.val = Nil.size = 0;
     81     int len = 1, i;
     82     while(!isalpha(*tmp = getchar()));
     83     while(isalpha(tmp[len] = getchar()))++len;
     84     getd(M);
     85     const int m = min(M + len, maxn - 1);
     86     *pow1 = 1;
     87     for(i = 1;i <= m;++i)
     88         pow1[i] = pow1[i-1]*p1;
     89     Root = newT(tmp, len);
     90 }
     91 inline bool check(int x, int y, int len){
     92     Splay *t;
     93     ull h11, h21;
     94     if(x == 1){
     95         find(Root, len + 1);
     96         t = Root->son[0];
     97     }
     98     else{
     99         find(Root, x - 1);
    100         find(Root->son[1], len + 1);
    101         t = Root->son[1]->son[0];
    102     }
    103     h11 = t->h1;
    104      
    105     find(Root, y - 1);
    106     if(len == Root->son[1]->size)t = Root->son[1];
    107     else{
    108         find(Root->son[1], len + 1);
    109         t = Root->son[1]->son[0];
    110     }
    111     h21 = t->h1;
    112     if(h11 != h21)return 0;
    113     return 1;
    114 }
    115 inline void Query(){
    116     int l = 1, r, x, y, mid;
    117     getd(x), getd(y);
    118     if(x > y)x ^= y ^= x ^= y;
    119     r = Root->size - y + 1;
    120     if(x == y){
    121         printf("%d", r);
    122         if(M)putchar(' ');
    123         return;
    124     }
    125     while(l <= r){
    126         mid = (l + r) >> 1;
    127         if(check(x, y, mid))l = mid + 1;
    128         else r = mid - 1;
    129     }
    130     printf("%d", r);
    131     if(M)putchar(' ');
    132 }
    133 inline void Change(){
    134     int x, d;
    135     getd(x);while(!isalpha(d = getchar()));d -= 'a';
    136     find(Root, x);
    137     Root->val = d;
    138     Root->update();
    139 }
    140 inline void Insert(){
    141     int x, d;
    142     getd(x);while(!isalpha(d = getchar()));
    143     Splay *t = Pool[iter++].init(d - 'a');
    144     if(!x){
    145         t->son[1] = Root;
    146         Root = t;
    147         Root->update();
    148         return;
    149     }
    150     find(Root, x);
    151     t->son[1] = Root->son[1];Root->son[1] = t;
    152     t->update(); Root->update();
    153 }
    154 int main(){
    155     #if defined DEBUG
    156     freopen("test""r", stdin);
    157     freopen("out.txt""w", stdout);
    158     #else
    159     //freopen("bzoj_1014.in", "r", stdin);
    160     //freopen("bzoj_1014.out", "w", stdout);
    161     #endif
    162     int opt;
    163     init();
    164     while(M--){
    165         while(!isalpha(opt = getchar()));
    166         if(opt == 'Q')
    167             Query();
    168 
    169         else if(opt == 'R')Change();
    170         else Insert();
    171     }
    172     #if defined DEBUG
    173     cout << endl<< (double)clock() / CLOCKS_PER_SEC << " sec" << endl;
    174     #endif
    175     return 0;
    176 }
    Splay Tree维护字符串哈希(单哈希+自然溢出)
  • 相关阅读:
    Day3-spark基本认识
    团队冲刺第九天
    团队冲刺第八天
    团队冲刺第七天
    团队冲刺第六天
    团队冲刺第五天
    团队冲刺第四天
    团队冲刺第三天
    团队冲刺第二天
    团队冲刺第一天
  • 原文地址:https://www.cnblogs.com/Asm-Definer/p/4371385.html
Copyright © 2011-2022 走看看