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