• 1014: [JSOI2008]火星人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
    数据规模:
    对于100%的数据,满足:
    1、 所有字符串自始至终都只有小写字母构成。
    2、 M <= 150,000
    3、 字符串长度L自始至终都满足L <= 100,000
    4、 询问操作的个数不超过10,000个。

    对于第1,2个数据,字符串长度自始至终都不超过1,000
    对于第3,4,5个数据,没有插入操作。

    看了题解,知道使用splay维护hash值,但是严重超时(自己评测还好,bzoj上时间是两倍多)

    没办法,看AC代码,对着调,发现取得hash值的方法不同

    它的做法:先把l旋到根,然后向右边遍历,取hash值,取完之后如果发现深度太大(根据自己的情况而定,它取得40,我取的23)就把它旋到根,在程序里用一个step记录深度

      1 type
      2     node=record
      3     son:array[0..1]of longint;
      4       fa,a,size:longint;
      5       hash:int64;
      6     end;
      7 const
      8     maxn=100010;
      9     h=10000007;
     10 var
     11     tree:array[0..maxn]of node;
     12     n,root,len,tot:longint;
     13     mi:array[0..maxn]of int64;
     14     s:array[0..maxn]of char;
     15  
     16 procedure swap(var x,y:longint);
     17 var
     18     t:longint;
     19 begin
     20     t:=x;x:=y;y:=t;
     21 end;
     22  
     23 procedure new(x:longint);
     24 begin
     25     with tree[x] do
     26       begin
     27         size:=1+tree[son[0]].size+tree[son[1]].size;
     28         hash:=((tree[son[0]].hash*27+a)*mi[tree[son[1]].size]+tree[son[1]].hash)mod h;
     29       end;
     30 end;
     31  
     32 function build(l,r,f:longint):longint;
     33 var
     34     mid:longint;
     35 begin
     36     mid:=(l+r)>>1;
     37     if (mid<>1) and (mid<>len+2) then tree[mid].a:=ord(s[mid-1])-ord('a')+1;
     38     with tree[mid] do
     39       begin
     40         fa:=f;
     41         hash:=a;
     42         if mid>l then son[0]:=build(l,mid-1,mid);
     43         if mid<r then son[1]:=build(mid+1,r,mid);
     44       end;
     45     new(mid);
     46     exit(mid);
     47 end;
     48  
     49 procedure init;
     50 var
     51     i:longint;
     52 begin
     53     while not eoln do
     54       begin
     55         inc(len);
     56         read(s[len]);
     57       end;
     58     mi[0]:=1;
     59     for i:=1 to 100010 do
     60       mi[i]:=mi[i-1]*27 mod h;
     61     root:=build(1,len+2,0);
     62     tot:=len+2;
     63 end;
     64  
     65 procedure rotate(x,w:longint);
     66 var
     67     y:longint;
     68 begin
     69     with tree[x] do
     70       begin
     71         y:=fa;
     72         tree[y].son[w]:=son[1 xor w];
     73         if son[1 xor w]<>0 then tree[son[1 xor w]].fa:=fa;
     74         son[1 xor w]:=y;
     75         if root=y then root:=x
     76         else
     77           if tree[tree[y].fa].son[0]=y then tree[tree[y].fa].son[0]:=x
     78           else tree[tree[y].fa].son[1]:=x;
     79         fa:=tree[y].fa;
     80         tree[y].fa:=x;
     81         new(y);
     82       end;
     83 end;
     84  
     85 procedure splay(x,z:longint);
     86 begin
     87     with tree[x] do
     88       while fa<>z do
     89         begin
     90           if tree[fa].fa=z then
     91             if tree[fa].son[0]=x then rotate(x,0)
     92             else rotate(x,1)
     93           else
     94             begin
     95               if tree[fa].son[0]=x then
     96                 if tree[tree[fa].fa].son[0]=fa then
     97                   begin
     98                     rotate(fa,0);
     99                     rotate(x,0);
    100                   end
    101                 else
    102                   begin
    103                     rotate(x,0);
    104                     rotate(x,1);
    105                   end
    106               else
    107                 if tree[tree[fa].fa].son[0]=fa then
    108                   begin
    109                     rotate(x,1);
    110                     rotate(x,0);
    111                   end
    112                 else
    113                   begin
    114                     rotate(fa,1);
    115                     rotate(x,1);
    116                   end;
    117             end;
    118         end;
    119     new(x);
    120 end;
    121  
    122 function find(x:longint):longint;
    123 begin
    124     find:=root;
    125     while x<>0 do
    126       with tree[find] do
    127         begin
    128           if x<=tree[son[0]].size then find:=son[0]
    129           else
    130             if x=tree[son[0]].size+1 then exit(find)
    131             else
    132               begin
    133                 dec(x,tree[son[0]].size+1);
    134                 find:=son[1];
    135               end;
    136         end;
    137 end;
    138  
    139 function get(l,len:longint):int64;
    140 var
    141     now,step:longint;
    142 begin
    143     splay(find(l+1),0);
    144     now:=tree[root].son[1];
    145     dec(len);
    146 step:=0;
    147     get:=tree[root].a;
    148     while len>0 do
    149       begin
    150 inc(step);
    151         if len=tree[now].size then
    152         begin
    153           get:=(get*mi[len]+tree[now].hash)mod h;
    154 if step>23 then splay(now,0);
    155           exit;
    156         end;
    157         if len=tree[tree[now].son[0]].size+1 then
    158         begin
    159           get:=(get*mi[len]+tree[tree[now].son[0]].hash*27+tree[now].a)mod h;
    160 if step>23 then splay(now,0);
    161           exit;
    162         end;
    163         if len<=tree[tree[now].son[0]].size then now:=tree[now].son[0]
    164         else
    165           begin
    166             get:=(get*mi[tree[tree[now].son[0]].size+1]+tree[tree[now].son[0]].hash*27+tree[now].a)mod h;
    167             dec(len,tree[tree[now].son[0]].size+1);
    168             now:=tree[now].son[1];
    169           end;
    170       end;
    171 end;
    172  
    173 procedure q;
    174 var
    175     l,r,left,right,mid:longint;
    176 begin
    177     readln(l,r);
    178     if l>r then swap(l,r);
    179     left:=0;
    180     right:=len-r+1;
    181     while left<right do
    182       begin
    183         mid:=(left+right+1)>>1;
    184         if get(l,mid)=get(r,mid) then left:=mid
    185         else right:=mid-1;
    186       end;
    187     writeln(left);
    188 end;
    189  
    190 procedure r;
    191 var
    192     s:char;
    193     x:longint;
    194 begin
    195     read(x,s,s);
    196     splay(find(x+1),0);
    197     tree[root].a:=ord(s)-ord('a')+1;
    198     new(root);
    199     readln;
    200 end;
    201  
    202 procedure ins;
    203 var
    204     s:char;
    205     x:longint;
    206 begin
    207     inc(len);
    208     read(x,s,s);
    209     x:=find(x+1);
    210     splay(x,0);
    211     inc(tot);
    212     with tree[tot] do
    213       begin
    214         a:=ord(s)-ord('a')+1;
    215         son[1]:=tree[x].son[1];
    216         tree[son[1]].fa:=tot;
    217         tree[x].son[1]:=tot;
    218         fa:=x;
    219       end;
    220     new(tot);
    221     new(x);
    222     readln;
    223 end;
    224  
    225 procedure work;
    226 var
    227     s:char;
    228     i,m:longint;
    229 begin
    230     readln(m);
    231     for i:=1 to m do
    232       begin
    233         read(s);
    234         case s of
    235           'Q':q;
    236           'R':r;
    237           'I':ins;
    238         end;
    239       end;
    240 end;
    241  
    242 begin
    243     init;
    244     work;
    245 end.
    View Code
  • 相关阅读:
    Insert into select语句把生产服务器炸了!
    人人都能看懂的 6 种限流实现方案
    Idea 快捷生成类注释与方法注释
    拦截器
    java 泛型
    SQL语句总结
    深入浅出Git教程(转载)
    (转载)CSS3与页面布局学习总结(三)——BFC、定位、浮动、7种垂直居中方法
    css中常见margin塌陷问题之解决办法
    css中固定宽高div与不固定宽高div垂直居中的处理办法
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3623412.html
Copyright © 2020-2023  润新知