• BZOJ 1014 火星人prefix


    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个数据,没有插入操作。


    Source

     r_64大神犇告诉我splay+二分+哈希,因此我就写了一发,复杂度O(nlogn^2)。
    代码:
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 using namespace std;
      6 
      7 #define rhl 37
      8 #define maxl 100010
      9 #define maxm 150010
     10 char s[maxl]; int len;
     11 unsigned long long mi[maxl+maxm];
     12 
     13 struct SPLAY
     14 {
     15     int ch[maxl+maxm][2],fa[maxl+maxm],size[maxl+maxm],key[maxl+maxm],cnt,root;
     16     unsigned long long hash[maxl+maxm];
     17 
     18     inline void updata(int x)
     19     {
     20         size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
     21         hash[x] = hash[ch[x][0]] * mi[size[ch[x][1]]+1] + mi[size[ch[x][1]]] * (key[x]) + hash[ch[x][1]];
     22     }
     23     
     24     inline void rotate(int x)
     25     {
     26         int y = fa[x],z = fa[y],l,r;
     27         if (ch[y][0] == x) l = 0; else l = 1; r = l ^ 1;
     28         if (z != 0)
     29         {
     30             if (ch[z][0] == y) ch[z][0] = x; else ch[z][1] = x;
     31         }
     32         fa[x] = z; fa[y] = x; fa[ch[x][r]] = y;
     33         ch[y][l] = ch[x][r]; ch[x][r] = y;
     34         updata(y); updata(x);
     35         fa[0] = 0; ch[0][0] = ch[0][1] = 0;
     36     }
     37     
     38     inline void splay(int x,int aim)
     39     {
     40         int t = fa[aim];
     41         while (fa[x] != t)
     42         {
     43             int y = fa[x],z = fa[y];
     44             if (fa[y] != t)
     45             {
     46                 if ((ch[y][0] == x)^(ch[z][0] == y)) rotate(x);
     47                 else rotate(y);
     48             }
     49             rotate(x);
     50         }
     51         if (aim == root) root = x;
     52     }
     53     
     54     inline int find(int rank,int have,int now)
     55     {
     56         if (size[ch[now][0]]+have+1==rank) return now;
     57         if (size[ch[now][0]]+have+1 > rank) return find(rank,have,ch[now][0]);
     58         else return find(rank,have+size[ch[now][0]]+1,ch[now][1]);
     59     }
     60     
     61     inline void init(int l,int r,int f)
     62     {
     63         int p; cnt = 0; root = 1;
     64         build(l,r,f);
     65         p = find(len,0,root);
     66         splay(p,root);
     67         fa[++cnt] = p;
     68         ch[p][1] = cnt;
     69         key[cnt] = 0;
     70         size[cnt] = 1;
     71         updata(p);
     72         p = find(1,0,root);
     73         splay(p,root);
     74         fa[++cnt] = p;
     75         ch[p][0] = cnt;
     76         key[cnt] = 0;
     77         size[cnt] = 1;
     78         updata(p);
     79     }
     80     
     81     inline void build(int l,int r,int f)
     82     {
     83         fa[++cnt] = f;
     84         if (l == r)
     85         {
     86             key[cnt] = s[l-1] - 'a' + 1;
     87             hash[cnt] = key[cnt];
     88             size[cnt] = 1;
     89             return;
     90         }
     91         int mid = (l+r)>>1,now = cnt;
     92         key[now] = s[mid-1] - 'a' + 1;
     93         if (mid > l)
     94         {
     95             ch[now][0] = cnt + 1;
     96             build(l,mid - 1,now);
     97         }
     98         if (mid  < r)
     99         {
    100             ch[now][1] = cnt+1;
    101             build(mid+1,r,now);
    102         }
    103         updata(now);
    104     }
    105 
    106     inline void change(int a,char b)
    107     {
    108         int p = find(a+1,0,root);
    109         splay(p,root);
    110         key[p] = b-'a'+1;
    111         updata(p);
    112     }
    113 
    114     inline void insert(int a,char b)
    115     {
    116         int p = find(a+1,0,root),q = find(a+2,0,root);
    117         splay(p,root);
    118         splay(q,ch[p][1]);
    119         fa[++cnt] = q;
    120         ch[q][0] = cnt; key[cnt] = b-'a'+1;
    121         updata(cnt);
    122         updata(q);
    123         updata(p);
    124     }
    125 
    126     inline unsigned long long calc(int a,int b)
    127     {
    128         int p = find(a,0,root),q = find(b+2,0,root);
    129         splay(p,root);
    130         splay(q,ch[p][1]);
    131         return hash[ch[q][0]];
    132     }
    133 }tree;
    134 
    135 inline int ask(int a,int b)
    136 {
    137     int l = 1,r = min(len-a+1,len-b+1),mid;
    138     while (l <= r)
    139     {
    140         mid = (l + r) >> 1;
    141         unsigned long long h1 = tree.calc(a,a+mid-1),h2 = tree.calc(b,b+mid-1);
    142         if (h1 == h2)
    143             l = mid+1;
    144         else r = mid - 1;
    145     }
    146     return r;
    147 }
    148 
    149 inline void ready()
    150 {
    151     mi[0] = 1;
    152     for (int i = 1;i < maxl+maxm;++i)
    153         mi[i] = rhl*mi[i-1];
    154 }
    155 
    156 inline int read()
    157 {
    158     int x=0,f=1;char ch=getchar();
    159     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    160     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    161     return x*f;
    162 }
    163 
    164 int main()
    165 {
    166     freopen("1014.in","r",stdin);
    167     freopen("1014.out","w",stdout);
    168     scanf("%s",s); len = strlen(s);
    169     ready();
    170     tree.init(1,len,0);
    171     int T = read(); char opt;
    172     while (T--)
    173     {
    174         scanf("%c",&opt);
    175         if (opt == 'Q')
    176         {
    177             int a = read(),b = read();
    178             printf("%d
    ",ask(a,b));
    179         }
    180         else if (opt == 'R')
    181         {
    182             int a = read(); char b; scanf("%c
    ",&b);
    183             tree.change(a,b);
    184         }
    185         else
    186         {
    187             int a = read(); char b; scanf("%c
    ",&b);
    188             tree.insert(a,b); ++len;
    189         }
    190     }
    191     fclose(stdin); fclose(stdout);
    192     return 0;
    193 }
    View Code
  • 相关阅读:
    HeapSpray初窥(2014.12)
    CVE-2014-4115漏洞分析(2014.11)
    【原创】oracle提权执行命令工具oracleShell v0.1
    【原创】贴个dirtycow(脏牛漏洞)不死机的exploit
    【CVE-2016-10009】OpenSSH < 7.4
    关于elasticsearch和kibana的时区和日期问题
    这是我写过的最长的正则表达式,没有之一
    三生缘
    【原创】JEECMS v6~v7任意文件上传漏洞(2)
    【原创】JEECMS v6~v7任意文件上传漏洞(1)
  • 原文地址:https://www.cnblogs.com/mmlz/p/4227380.html
Copyright © 2020-2023  润新知