zoukankan      html  css  js  c++  java
  • JSOI2008 火星人prefix

    http://61.187.179.132/JudgeOnline/problem.php?id=1014

    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

    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值,这样卡区间替换加入什么的就都可以实现了。对于每次询问二分答案出解即可。略微奇葩的是我的hash一开始怎么写都过不了,不取模了之后瞬间就A了,按理说应该取模的……………………
     
    View Code
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<algorithm>
      5 
      6 using namespace std;
      7 
      8 const int maxn=300000;
      9 const unsigned int hehe=27;
     10 
     11 int m,l;
     12 
     13 char s[maxn];
     14 
     15 unsigned int bit[maxn];
     16 
     17 struct node
     18 {
     19     int l,r,f,size,c;
     20     unsigned int v;
     21     node()
     22     {
     23         l=r=f=size=c=v=0;
     24     }
     25 };
     26 
     27 struct splay_tree
     28 {
     29     int root,size;
     30     node z[maxn];
     31     void update(int now)
     32     {
     33         z[now].size=z[z[now].l].size+z[z[now].r].size+1;
     34         z[now].v=(z[z[now].r].v+bit[z[z[now].r].size]*z[now].c+z[z[now].l].v*bit[z[z[now].r].size+1]);
     35     }
     36     void rot_r(int now)
     37     {
     38         int a=z[now].l;
     39         z[now].l=z[a].r;
     40         z[a].r=now;
     41         if (root==now) root=a;
     42         else
     43         {
     44             if (z[z[now].f].l==now) z[z[now].f].l=a;
     45             else z[z[now].f].r=a;
     46         }
     47         z[a].f=z[now].f;
     48         z[now].f=a;
     49         z[z[now].l].f=now;
     50         update(now);
     51         update(a);
     52     }
     53     void rot_l(int now)
     54     {
     55         int a=z[now].r;
     56         z[now].r=z[a].l;
     57         z[a].l=now;
     58         if (root==now) root=a;
     59         else
     60         {
     61             if (z[z[now].f].l==now) z[z[now].f].l=a;
     62             else z[z[now].f].r=a;
     63         }
     64         z[a].f=z[now].f;
     65         z[now].f=a;
     66         z[z[now].r].f=now;
     67         update(now);
     68         update(a);
     69     }
     70     void splay(int now,int goal)
     71     {
     72         while (z[now].f!=goal)
     73         {
     74             int f=z[now].f;
     75             int ff=z[f].f;
     76             if (ff==goal)
     77             {
     78                 if (z[f].l==now) rot_r(f);
     79                 else rot_l(f);
     80             }
     81             else
     82             {
     83                 if ((z[ff].l==f) && (z[f].l==now))
     84                 {
     85                     rot_r(ff);
     86                     rot_r(f);
     87                 }
     88                 if ((z[ff].r==f) && (z[f].r==now))
     89                 {
     90                     rot_l(ff);
     91                     rot_l(f);
     92                 }
     93                 if ((z[ff].l==f) && (z[f].r==now))
     94                 {
     95                     rot_l(f);
     96                     rot_r(ff);
     97                 }
     98                 if ((z[ff].r==f) && (z[f].l==now))
     99                 {
    100                     rot_r(f);
    101                     rot_l(ff);
    102                 }
    103             }
    104         }
    105         if (goal==0) root=now;
    106     }
    107     int find(int p)
    108     {
    109         int nowp=root;
    110         while (p)
    111         {
    112             if (z[z[nowp].l].size+1==p) return nowp;
    113             if (z[z[nowp].l].size<p) p-=z[z[nowp].l].size+1,nowp=z[nowp].r;
    114             else nowp=z[nowp].l;
    115         }
    116         return -1;
    117     }
    118     void find_seg(int l,int r)
    119     {
    120         int p1=find(l-1);
    121         int p2=find(r+1);
    122         splay(p1,0);
    123         splay(p2,p1);
    124     }
    125     void insert(int p,char c)
    126     {
    127         int nowp=find(p);
    128         splay(nowp,0);
    129         if (z[nowp].r)
    130         {
    131             nowp=z[nowp].r;
    132             while (z[nowp].l)
    133                 nowp=z[nowp].l;
    134             size++;
    135             z[size].f=nowp;
    136             z[size].v=z[size].c=c;
    137             z[size].l=z[size].r=0;
    138             z[size].size=1;
    139             z[nowp].l=size;
    140             splay(size,0);
    141         }
    142         else
    143         {
    144             size++;
    145             z[size].v=z[size].c=c;
    146             z[size].f=nowp;
    147             z[size].l=z[size].r=0;
    148             z[size].size=1;
    149             z[nowp].r=size;
    150             update(nowp);
    151         }
    152     }
    153     void replace(int p,char c)
    154     {
    155         int nowp=find(p);
    156         z[nowp].c=c;
    157         update(nowp);
    158         splay(nowp,0);
    159     }
    160     void build()
    161     {
    162         size=2+l;
    163         root=1;
    164         for (int a=2;a<=l+1;a++)
    165         {
    166             z[a].f=a-1;
    167             z[a].l=0;
    168             z[a].r=a+1;
    169             z[a].c=s[a-1];
    170         }
    171         z[1].f=0;
    172         z[1].l=0;
    173         z[1].r=2;
    174         z[1].c=0;
    175         z[size].f=l+1;
    176         z[size].l=z[size].r=0;
    177         z[size].v=z[size].c=0;
    178         z[size].size=1;
    179         for (int a=l+1;a>=1;a--)
    180             update(a);
    181     }
    182     unsigned int query(int l,int r)
    183     {
    184         find_seg(l,r);
    185         return z[z[z[root].r].l].v;
    186     }
    187     bool check(int x,int y)
    188     {
    189         int p1=find(x);
    190         int p2=find(y);
    191         if (z[p1].c!=z[p2].c) return false;
    192         else return true;
    193     }
    194 }tree;
    195 
    196 void getans(int p1,int p2)
    197 {
    198     if (!tree.check(p1+1,p2+1))
    199     {
    200         printf("0\n");
    201         return;
    202     }
    203     int r=l-p2+2;
    204     int l=1;
    205     while (l+1!=r)
    206     {
    207         int m=(l+r)>>1;
    208         if (tree.query(p1+1,p1+m)!=tree.query(p2+1,p2+m)) r=m;
    209         else l=m;
    210     }
    211     printf("%d\n",l);
    212 }
    213 
    214 int main()
    215 {
    216     freopen("prefix.in","r",stdin);
    217     freopen("prefix.out","w",stdout);
    218 
    219     scanf("%s",s+1);
    220     bit[0]=1;
    221     for (int a=1;a<maxn;a++)
    222         bit[a]=(bit[a-1]*hehe);
    223     l=strlen(s+1);
    224     for (int a=1;a<=l;a++)
    225         s[a]-='a'-1;
    226     tree.build();
    227     scanf("%d",&m);
    228     for (int a=1;a<=m;a++)
    229     {
    230         char s[2];
    231         scanf("%s",s);
    232         if (s[0]=='Q')
    233         {
    234             int x,y;
    235             scanf("%d%d",&x,&y);
    236             getans(min(x,y),max(x,y));
    237         }
    238         else
    239         {
    240             if (s[0]=='R')
    241             {
    242                 int x;
    243                 scanf("%d%s",&x,s);
    244                 s[0]-='a'-1;
    245                 tree.replace(x+1,s[0]);
    246             }
    247             else
    248             {
    249                 int x;
    250                 l++;
    251                 scanf("%d%s",&x,s);
    252                 s[0]-='a'-1;
    253                 tree.insert(x+1,s[0]);
    254             }
    255         }    
    256     }
    257 
    258     return 0;
    259 }
  • 相关阅读:
    webstorm 自定义代码模板
    HTML5 manifest ApplicationCache
    WebStorm 快捷键收藏
    函数内巧用注释实现多行文本拼接
    图片剪裁上传插件
    将json转为复杂url参数
    CSS3实现半像素边框
    打造自己的3D全景漫游
    自适应rem布局
    header页头内容整理
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2682847.html
Copyright © 2011-2022 走看看