zoukankan      html  css  js  c++  java
  • bzoj 1014[JSOI2008]火星人prefix

    1014: [JSOI2008]火星人prefix

    Time Limit: 10 Sec  Memory Limit: 162 MB

    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、询问。语法:Qxy,x,y均为正整数。功能:计算LCQ(x,y)限制:1<=x,y<=当前字符串长度。
    2、修改。语法:Rxd,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字
    符串长度。
    3、插入:语法:Ixd,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

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

    2、M<=150,000

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

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

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

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

    我们发现要支持修改操作,所以后缀数组就不适用了

    查询两个字符串的lcp有两个很常见的算法, 后缀数组和 二分哈希

    所以对于字符串的修改我们用一个splay 来维护, 平衡树每个节点表示的是对应子树的字符串的哈希值。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define LL long long
      6 using namespace std;
      7 
      8 const int MAXN = 1e5 + 10, MAXM = 2e5 + 10;
      9 int N, M;
     10 int root;
     11 int ans = 0;
     12 int tot = 0;
     13 char opr[30], d[30];
     14 unsigned long long pow[MAXN];
     15 struct spl {
     16     int ch[2];
     17     int fa;
     18     unsigned LL c;
     19     int size;
     20     unsigned LL hash;
     21     void init()
     22     {
     23         ch[0] = ch[1] = 0;
     24         size = 0;
     25         hash = 0;
     26         c = 0;
     27         fa = 0;
     28     }
     29 } t[MAXN * 50];
     30 inline LL read()
     31 {
     32     LL x = 0, w = 1; char ch = 0;
     33     while(ch < '0' || ch > '9') {
     34         if(ch == '-') {
     35             w = -1;
     36         }
     37         ch = getchar();
     38     }    
     39     while(ch >= '0' && ch <= '9') {
     40         x = x * 10 + ch - '0';
     41         ch = getchar();
     42     }
     43     return x * w;
     44 }
     45 
     46 char s[MAXN];
     47 
     48 void pushup(int k)
     49 {
     50     t[k].size = t[t[k].ch[0]].size + t[t[k].ch[1]].size + 1;
     51     t[k].hash = t[t[k].ch[0]].hash * pow[t[t[k].ch[1]].size + 1] + t[k].c * pow[t[t[k].ch[1]].size] + t[t[k].ch[1]].hash;
     52 }
     53 
     54 void rotate(int x, int &k)
     55 {
     56     int y = t[x].fa, z = t[y].fa;
     57     int l = 0, r;
     58     if(y == k) {
     59         k = x;
     60     }
     61     if(t[y].ch[0] == x) {
     62         l = 0;
     63     } else {
     64         l = 1;
     65     }
     66     r = l ^ 1;
     67     if(z) {
     68         if(t[z].ch[0] == y) {
     69             t[z].ch[0] = x;
     70         } else {
     71             t[z].ch[1] = x;
     72         }
     73     }
     74     int tt = t[x].ch[r];
     75     t[x].ch[r] = y, t[x].fa = z, t[tt].fa = y;
     76     t[y].ch[l] = tt, t[y].fa = x;
     77     pushup(y), pushup(x);
     78 }
     79 
     80 void splay(int x, int &k)
     81 {
     82     while(x != k) {
     83         int y = t[x].fa, z = t[y].fa;
     84         if(y != k) {
     85             if(t[z].ch[0] == y ^ t[y].ch[0] == x) {
     86                 rotate(x, k);
     87             } else {
     88                 rotate(y, k);
     89             }
     90         }
     91         rotate(x, k);
     92     }
     93 }
     94 
     95 unsigned LL judge(int st, int len)
     96 {
     97     int k = root;
     98     int loc = st;
     99     while(loc != t[t[k].ch[0]].size + 1) {
    100         if(loc > t[t[k].ch[0]].size) {
    101             loc = loc - t[t[k].ch[0]].size - 1;
    102             k = t[k].ch[1];
    103         } else {
    104             k = t[k].ch[0];    
    105         }
    106     }
    107     splay(k, root);
    108     k = root;
    109     loc = st + len + 1;
    110     while(loc != t[t[k].ch[0]].size + 1) {
    111         if(loc > t[t[k].ch[0]].size) {
    112             loc = loc - t[t[k].ch[0]].size - 1;
    113             k = t[k].ch[1];
    114         } else {
    115             k = t[k].ch[0];    
    116         }
    117     }
    118     splay(k, t[root].ch[1]);
    119     return t[t[t[root].ch[1]].ch[0]].hash;
    120 }
    121 
    122 void query(int x, int y)
    123 {
    124     int l = 0, r = tot - max(x, y) - 1;
    125     while(l <= r) {
    126         int mid = (l + r) >> 1;
    127     //    cout<<mid<<endl;
    128         if(judge(x, mid) == judge(y, mid)) {
    129             ans = mid;
    130             l = mid + 1;
    131         } else {
    132             r = mid - 1;
    133         }
    134     }
    135     printf("%d
    ", ans);
    136 }
    137 
    138 void update(int loc, char d)
    139 {
    140     int k = root;
    141     while(loc != t[t[k].ch[0]].size + 1) {
    142         if(loc > t[t[k].ch[0]].size) {
    143             loc = loc - t[t[k].ch[0]].size - 1;
    144             k = t[k].ch[1];
    145         } else {
    146             k = t[k].ch[0];    
    147         }
    148     }
    149     t[k].c = d - 'a';
    150 //    pushup(k);
    151     splay(k, root);
    152 }
    153 
    154 void insert(int x, char d)
    155 {
    156     int k = root;
    157     int loc = x;
    158     while(loc != t[t[k].ch[0]].size + 1) {
    159         if(loc > t[t[k].ch[0]].size) {
    160             loc = loc - t[t[k].ch[0]].size - 1;
    161             k = t[k].ch[1];
    162         } else {
    163             k = t[k].ch[0];    
    164         }
    165     }
    166     splay(k, root);
    167     loc = x + 1;
    168     k = root;
    169     while(loc != t[t[k].ch[0]].size + 1) {
    170         if(loc > t[t[k].ch[0]].size) {
    171             loc = loc - t[t[k].ch[0]].size - 1;
    172             k = t[k].ch[1];
    173         } else {
    174             k = t[k].ch[0];    
    175         }
    176     }
    177     splay(k, t[root].ch[1]);
    178     t[++tot].init();
    179     t[t[root].ch[1]].ch[0] = tot;
    180     t[tot].fa = t[root].ch[1];
    181     t[tot].size = 1;
    182     t[tot].hash = t[tot].c = d - 'a';
    183     pushup(t[root].ch[1]);
    184     pushup(root);
    185 }
    186 
    187 void build(int l, int r, int &k, int last)
    188 {
    189 //    cout<<l<<" "<<r<<endl;
    190     if(l > r) {
    191         return;
    192     }
    193     k = ++tot;
    194     if(l == r) {
    195         t[k].init();
    196         t[k].size = 1;
    197         t[k].c = t[k].hash = s[l] - 'a';
    198         t[k].fa = last;
    199         return;
    200     }
    201     int mid = (l + r) >> 1;
    202     t[k].init();
    203     t[k].size = 1;
    204     t[k].c = s[mid] - 'a';
    205     t[k].fa = last;
    206     build(l, mid - 1, t[k].ch[0], k);
    207     build(mid + 1, r, t[k].ch[1], k);
    208     pushup(k); 
    209 }
    210 
    211 void init()
    212 {
    213     pow[0] = 1;
    214     for(int i = 1; i <= 1e5; i++) {
    215         pow[i] = pow[i - 1] * 27;
    216     }
    217 }
    218 
    219 void print(int k)
    220 {
    221 //    cout<<t[k].ch[0]<<" "<<t[k].ch[1]<<" "<<char(t[k].c  + 'a')<<" "<<t[k].size<<" "<<t[k].hash<<endl;
    222 
    223     if(t[k].ch[0]) {
    224         print(t[k].ch[0]);
    225     }
    226     //cout<<char(t[k].c + 'a');
    227     if(t[k].ch[1]) {
    228         print(t[k].ch[1]);
    229     }
    230 }
    231 
    232 int main()
    233 {
    234     init();
    235 /*    for(int i = 1; i <= 10; i++) {
    236         cout<<pow[i]<<" ";
    237     }
    238     cout<<endl;*/
    239     t[0].init();
    240     scanf("%s", s + 1);
    241     N = strlen(s + 1);
    242     N++;
    243     s[0] = 'A';
    244     s[N] = 'A';
    245     build(0, N, root, 0);
    246 //    print(root);
    247     M = read();
    248     while(M--) {
    249         scanf("%s", opr);
    250         if(opr[0] == 'Q') {
    251             int x = read(), y = read();
    252             query(x, y);
    253         } else if(opr[0] == 'R') {
    254             int    x = read();
    255             scanf("%s", d);
    256             update(x + 1, d[0]);
    257         } else {
    258             int x = read();
    259             scanf("%s", d);
    260             insert(x + 1, d[0]);
    261         }
    262     }
    263     return 0;
    264 }
    265 
    266 /*
    267 madamimadam
    268 7
    269 Q 1 7
    270 Q 4 8
    271 Q 10 11
    272 R 3 a
    273 Q 1 7
    274 I 10 a
    275 Q 2 11
    276 */
    View Code
  • 相关阅读:
    静态成员 执行顺序
    排序之插入排序
    结构体字节对齐问题
    建模基础&UML
    C#中隐藏(new)和方法重载(overide)的区别
    培训记录
    C笔记
    用例
    .NET架构
    C#格式化日期
  • 原文地址:https://www.cnblogs.com/wuenze/p/8438103.html
Copyright © 2011-2022 走看看