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 }
原文地址:https://www.cnblogs.com/zhonghaoxi/p/2682847.html