1014: [JSOI2008]火星人prefix

题目连接:

http://www.lydsy.com/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

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

题意

题解:

用splay去维护就好了

询问就直接暴力二分判断就行了

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 1e6+7;
  4. const int mod = 1e9+7;
  5. const int P = 27;
  6. struct Splay
  7. {
  8. int fa[maxn];
  9. int ch[maxn][2];
  10. int val[maxn];
  11. int siz[maxn];
  12. long long h[maxn];
  13. long long p[maxn];
  14. int root,tot,n;
  15. char s[maxn];
  16. void newnode(int &r,int father,int k)//建立新的节点
  17. {
  18. r=++tot;
  19. fa[r]=father;
  20. val[r]=k;
  21. ch[r][0]=ch[r][1]=0;
  22. siz[r]=1;
  23. }
  24. void push_up(int x)
  25. {
  26. int l=ch[x][0],r=ch[x][1];
  27. siz[x]=siz[l]+siz[r]+1;
  28. h[x]=h[l]*p[siz[r]+1]+val[x]*p[siz[r]]+h[r];
  29. h[x]%=mod;
  30. }
  31. void zig(int x)
  32. {
  33. int y=fa[x];
  34. ch[y][0]=ch[x][1];
  35. fa[ch[x][1]]=y;
  36. ch[x][1]=y;
  37. fa[x]=fa[y];
  38. if(y==ch[fa[y]][0])
  39. ch[fa[y]][0]=x;
  40. else if(y==ch[fa[y]][1])
  41. ch[fa[y]][1]=x;
  42. fa[y]=x;
  43. push_up(y);
  44. if(y==root)root=x;
  45. }
  46. void zag(int x)
  47. {
  48. int y=fa[x];
  49. ch[y][1]=ch[x][0];
  50. fa[ch[x][0]]=y;
  51. ch[x][0]=y;
  52. fa[x]=fa[y];
  53. if(y==ch[fa[y]][0])
  54. ch[fa[y]][0]=x;
  55. else if(y==ch[fa[y]][1])
  56. ch[fa[y]][1]=x;
  57. fa[y]=x;
  58. push_up(y);
  59. if(y==root)root=x;
  60. }
  61. void splay(int x,int goal)
  62. {
  63. while(fa[x]!=goal)
  64. {
  65. int y=fa[x],z=fa[y];
  66. if(z==goal)
  67. {
  68. if(x==ch[y][0])
  69. zig(x);
  70. else
  71. zag(x);
  72. break;
  73. }
  74. if(x==ch[y][0])
  75. {
  76. if(y==ch[z][0])
  77. zig(y);
  78. zig(x);
  79. }
  80. else
  81. {
  82. if(y==ch[z][1])
  83. zag(y);
  84. zag(x);
  85. }
  86. }
  87. push_up(x);
  88. }
  89. void fi(int x,int rk,int z)
  90. {
  91. while(1)
  92. {
  93. if(rk<=siz[ch[x][0]])
  94. x=ch[x][0];
  95. else
  96. {
  97. rk-=siz[ch[x][0]];
  98. if(rk==1)break;
  99. rk--;
  100. x=ch[x][1];
  101. }
  102. }
  103. splay(x,z);
  104. }
  105. void build(int &x,int l,int r,int father)
  106. {
  107. if(l>r)return;
  108. int mid = (l+r)/2;
  109. newnode(x,father,s[mid]-'a'+1);
  110. if(l<mid)build(ch[x][0],l,mid-1,x);
  111. if(r>mid)build(ch[x][1],mid+1,r,x);
  112. push_up(x);
  113. }
  114. void init()
  115. {
  116. p[0]=1;
  117. for(int i=1;i<maxn;i++)
  118. p[i]=p[i-1]*P%mod;
  119. scanf("%s",s);
  120. n=strlen(s);
  121. newnode(root,0,1);
  122. newnode(ch[root][1],root,1);
  123. siz[root]=2;
  124. build(ch[ch[root][1]][0],0,n-1,ch[root][1]);
  125. push_up(ch[root][1]);
  126. push_up(root);
  127. }
  128. long long query(int x,int len)
  129. {
  130. fi(root,x,0);
  131. fi(root,x+len+1,root);
  132. //if(len==1)return val[ch[ch[root][1]][0]];
  133. //printf("%c %c %lld\n",val[ch[ch[root][1]][0]]+'a'-1,val[ch[root][1]]+'a'-1,h[ch[ch[root][1]][0]]);
  134. return h[ch[ch[root][1]][0]];
  135. }
  136. int solve(int x,int y)
  137. {
  138. int l=1,r=min(siz[root]-x,siz[root]-y)-1;
  139. int ans=0;
  140. while(l<=r)
  141. {
  142. int mid = (l+r)/2;
  143. if(query(x,mid)==query(y,mid))l=mid+1,ans=mid;
  144. else r=mid-1;
  145. }
  146. return ans;
  147. }
  148. void change(int x,int y)
  149. {
  150. fi(root,x+1,0);
  151. val[root]=y;
  152. push_up(root);
  153. }
  154. void in(int x,int y)
  155. {
  156. fi(root,x+1,0);
  157. fi(root,x+2,root);
  158. newnode(ch[ch[root][1]][0],ch[root][1],y);
  159. push_up(ch[ch[root][1]][0]);
  160. push_up(ch[root][1]);
  161. push_up(root);
  162. }
  163. }T;
  164. int main()
  165. {
  166. T.init();
  167. int q;scanf("%d",&q);
  168. while(q--)
  169. {
  170. char c[10];
  171. scanf("%s",c);
  172. if(c[0]=='R')
  173. {
  174. int x;char k[10];
  175. scanf("%d%s",&x,k);
  176. T.change(x,k[0]-'a'+1);
  177. }
  178. else if(c[0]=='I')
  179. {
  180. int x;char k[10];
  181. scanf("%d%s",&x,k);
  182. T.in(x,k[0]-'a'+1);
  183. }
  184. else
  185. {
  186. int x,y;scanf("%d%d",&x,&y);
  187. printf("%d\n",T.solve(x,y));
  188. }
  189. }
  190. }

BZOJ 1014: [JSOI2008]火星人prefix Splay+二分的更多相关文章

  1. BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6243  Solved: 2007[Submit] ...

  2. BZOJ 1014 [JSOI2008]火星人prefix (splay+二分答案+字符串hash)

    题目大意:维护一个字符串,支持插入字符和替换字符的操作,以及查询该字符串两个后缀的最长公共前缀长度 乍一看以为是后缀数组,然而并没有可持久化后缀数组(雾) 看题解才知道这是一道splay题,首先要对s ...

  3. BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8112  Solved: 2569[Submit] ...

  4. BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

    用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...

  5. bzoj 1014 [JSOI2008]火星人prefix——splay+哈希

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 用splay维护字符串,每个点记录子树的哈希值,然后二分查询. 二分不是把两个点的哈希 ...

  6. BZOJ 1014 [JSOI2008]火星人prefix | Splay维护哈希值

    题目: 题解: #include<cstdio> #include<algorithm> #include<cstring> typedef long long l ...

  7. bzoj 1014: [JSOI2008]火星人prefix hash && splay

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3154  Solved: 948[Submit][ ...

  8. 求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4164  Solved: 1277[Submit] ...

  9. [BZOJ 1014] [JSOI2008] 火星人prefix 【Splay + Hash】

    题目链接:BZOJ - 1014 题目分析 求两个串的 LCP ,一种常见的方法就是 二分+Hash,对于一个二分的长度 l,如果两个串的长度为 l 的前缀的Hash相等,就认为他们相等. 这里有修改 ...

随机推荐

  1. Spring3.0.6定时任务

    项目使用的Spring版本比较旧是3.0.6版本,由于需要进行定时任务,就决定使用Spring自带的scheduled task. 在网上找了很多文章,也查看了Spring3.0.6的官方文档,按照网 ...

  2. 获取当前的 viewController

    - (UIViewController *)currentController {    UIViewController *result = nil;    UIWindow *window = [ ...

  3. Python【基础第二篇】

    元组 元组的元素不可修改 元组的元素的元素可修改 字典 Python主文件判断 name == main python中一切事物都是对象 对象是基于类创建的 对象具有的所有功能都是从类里找的 int内 ...

  4. WebGIS的大众化服务

    WebGIS是Web技术与GIS相结合的产物.WebGIS的真正意义在于,它将GIS从专业应用推向了大众化服务,同时为地理信息共享提供了方便而有效的途径. 一.ESRI大会关于WebGIS的报告 纵观 ...

  5. pku3659 Cell Phone Network

    http://poj.org/problem?id=3659 树状DP,树的最小点覆盖 #include <stdio.h> #include <vector> #define ...

  6. 第二百零七天 how can I坚持

    都这么一大把年纪了,还没正事,哎.. mysql ifnull(expr,expr),oracle nvl();去null函数. 每天也没什么事. 哎,每天 也总有那么点事. 刘松.李承杰,都是些什么 ...

  7. [转载]开机出现A disk read error occurred错误

    [此文章转载] 今天维修了一台机器,郁闷之极.最开始一直无法正确安装操作系统,一安装总是提示文件无法写入内存.换了光盘.光驱都无济于事,忽然意识到是不是内存的问题,随即找了一个内存来,替换了一下,更郁 ...

  8. Codeforces 219D. Choosing Capital for Treeland (树dp)

    题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...

  9. POJ2299Ultra-QuickSort (线段树和归并排序的解法)

    题目大意就是说帮你给一些(n个)乱序的数,让你求冒泡排序需要交换数的次数(n<=500000) 此题最初真不会做,我也只是在听了章爷的讲解后才慢慢明白过来的 首先介绍线段树的解法: 我们先将原数 ...

  10. Lotus 迁移到Exchange 2010 之准备使用Transport 同步Lotus 相关信息!

    这里我们先来分析下Lotus迁移到Exchange2010 的一些原理,由于存在一定周期的共存时间,因此在共存期间必须来实现相应的同步计划,整个同步计划包含了如下的同步计划: