看了《Hash在信息学竞赛中的一类应用》中的例题3,这道题很类似啊,只不过没有删点和区间翻转。

用Splay维护字符串哈希,加点改点什么的就不用说了,查询时二分答案,这样时间复杂度是$O(mlog^2 n)$的

论文的例题3中删点很简单,和插点一样,不用说了,区间翻转只要打一个翻转标记,维护正序hash和逆序hash,翻转时交换两个hash值即可。

对拍终于成功了QAQ,插点时孩子不认父亲TwT又手残了~

《Hash在信息学竞赛中的一类应用》中还提到了块状链表的做法,都很易懂:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N = 100003;
  7. const int p = 9875321;
  8.  
  9. int P[N];
  10. struct node *null;
  11. struct node {
  12. node *ch[2], *fa;
  13. int k, s, ha;
  14. node (int _k = 0) {k = _k; s = 1; ha = _k; ch[0] = ch[1] = fa = null;}
  15. void setc(node *r, bool c) {this->ch[c] = r; r->fa = this;}
  16. bool pl() {return fa->ch[1] == this;}
  17. void count() {
  18. s = ch[0]->s + ch[1]->s + 1;
  19. ha = ((ch[0]->ha + 1ll * k * P[ch[0]->s]) % p + 1ll * ch[1]->ha * P[ch[0]->s + 1] % p) % p;
  20. }
  21. } *root;
  22.  
  23. int n, m;
  24. char s[N];
  25.  
  26. namespace Splay {
  27. node *Build(int l, int r) {
  28. if (l > r) return null;
  29. int mid = (l + r) >> 1;
  30. node *t = new node(s[mid] - 'a');
  31. t->ch[0] = Build(l, mid - 1); t->setc(t->ch[0], 0);
  32. t->ch[1] = Build(mid + 1, r); t->setc(t->ch[1], 1);
  33. t->count();
  34. return t;
  35. }
  36. void init() {
  37. P[0] = 1; for(int i = 1; i < N; ++i) P[i] = P[i - 1] * 26 % p;
  38. null = new node; null->s = 0; null->ch[0] = null->ch[1] = null->fa = null;
  39. scanf("%s", s + 1); n = strlen(s + 1); root = Build(1, n);
  40. }
  41. void rotate(node *r) {
  42. node *f = r->fa;
  43. bool c = r->pl();
  44. if (f != root) f->fa->setc(r, f->pl());
  45. else root = r, r->fa = null;
  46. f->setc(r->ch[!c], c);
  47. r->setc(f, !c);
  48. f->count();
  49. }
  50. void splay(node *r, node *tar = null) {
  51. for(; r->fa != tar; rotate(r))
  52. if (r->fa->fa != tar) rotate(r->pl() == r->fa->pl() ? r->fa : r);
  53. r->count();
  54. }
  55. node *kth(int k) {
  56. node *r = root;
  57. while (1) {
  58. if (r->ch[0]->s >= k) r = r->ch[0];
  59. else if (r->ch[0]->s + 1 >= k) return r;
  60. else k -= (r->ch[0]->s + 1), r = r->ch[1];
  61. }
  62. }
  63. int hash(int l, int r) {
  64. if (l == 1 && r == n) return root->ha;
  65. else if (l == 1) {splay(kth(r + 1)); return root->ch[0]->ha;}
  66. else if (r == n) {splay(kth(l - 1)); return root->ch[1]->ha;}
  67. else {splay(kth(l - 1)); splay(kth(r + 1), root); return root->ch[1]->ch[0]->ha;}
  68. }
  69. void QQ(int l, int r) {
  70. int left = 0, right = root->s - max(l, r) + 1, mid;
  71. while (left < right) {
  72. mid = (left + right + 1) >> 1;
  73. if (hash(l, l + mid - 1) == hash(r, r + mid - 1)) left = mid;
  74. else right = mid - 1;
  75. }
  76. printf("%d\n", left); return;
  77. }
  78. void RR(int k, int num) {
  79. node *r = kth(k);
  80. r->k = num;
  81. splay(r);
  82. }
  83. void II(int k, int num) {
  84. if (k == 0) {
  85. node *r = root;
  86. while (r->ch[0] != null) r = r->ch[0];
  87. r->setc(new node(num), 0);
  88. splay(r->ch[0]);
  89. } else {
  90. splay(kth(k));
  91. if (k == n) {
  92. root->setc(new node(num), 1);
  93. splay(root->ch[1]);
  94. } else {
  95. splay(kth(k + 1), root);
  96. root->ch[1]->setc(new node(num), 0);
  97. splay(root->ch[1]->ch[0]);
  98. }
  99. }
  100. ++n;
  101. }
  102. }
  103.  
  104. int main() {
  105. Splay::init();
  106. scanf("%d", &m);
  107. char c; int x, y;
  108. while (m--) {
  109. for(c = getchar(); c < 'A' || c > 'Z'; c = getchar());
  110. switch (c) {
  111. case 'Q':
  112. scanf("%d%d", &x, &y);
  113. Splay::QQ(x, y);
  114. break;
  115. case 'R':
  116. scanf("%d", &x); for(c = getchar(); c < 'a' || c > 'z'; c = getchar());
  117. Splay::RR(x, c - 'a');
  118. break;
  119. case 'I':
  120. scanf("%d", &x); for(c = getchar(); c < 'a' || c > 'z'; c = getchar());
  121. Splay::II(x, c - 'a');
  122. break;
  123. }
  124. }
  125. return 0;
  126. }

对拍大法好~

【BZOJ 1014】【JSOI 2008】火星人prefix的更多相关文章

  1. JSOI 2008 火星人prefix

    FROM http://www.lydsy.com/JudgeOnline/problem.php?id=1014 LCP问题 给定串 S[0..n] , 对于一对(a,b)其中0<a,b< ...

  2. Bzoj 1014&Luogu 4036 火星人Prefix(FHQ-Treap)

    题面 洛谷 Bzoj 题解 首先,这种带修改的是不能用$SA$的,然后,我们做$SA$的题一般也能二分+$Hash$,所以不妨考虑用$FHQ-Treap$维护树,然后查询就用二分+$Hash$. $H ...

  3. 【BZOJ 1014】 [JSOI2008]火星人prefix

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1014 [题意] 让你在线查询最长公共前缀. 支持单节点修改; 插入操作; [题解] / ...

  4. [BZOJ 1013][JSOI 2008] 球形空间产生器sphere 题解(高斯消元)

    [BZOJ 1013][JSOI 2008] 球形空间产生器sphere Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球 面 ...

  5. [BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap)

    [BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap) 题面 给出一个长度为n的字符串,m个操作,字符串仅包含小写英文字母 操作1:在k ...

  6. BZOJ 1016 JSOI 2008 最小生成树计数 Kruskal+搜索

    题目大意:给出一些边,求出一共能形成多少个最小生成树. 思路:最小生成树有非常多定理啊,我也不是非常明确.这里仅仅简单讲讲做法.关于定各种定理请看这里:http://blog.csdn.net/wyf ...

  7. 【BZOJ】【1014】【JLOI2008】火星人prefix

    Splay/二分/Hash 看了网上的题目关键字(都不用点进去看……我也是醉了)了解到做法= =那就上呗,前面做了好几道Splay的题就是为了练手搞这个的. Hash判断字符串是否相同应该很好理解吧? ...

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

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

  9. BZOJ 1014: [JSOI2008]火星人prefix Splay+二分

    1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...

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

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

随机推荐

  1. 微信支付 总提示get_brand_wcpay_request:fail 也不跳转支付页面 的解决方案

    最近在做微信支付,帮客户部署好环境后,测试微信支付,发现点击支付后老是提示: get_brand_wcpay_request:fail, 于是找到代码中调用微信支付的代码段: WeixinJSBrid ...

  2. Activity的onCreate()的PersistableBundle 参数坑。

    Bundle 与 PersistableBundle 区别 仅仅是Activity oncreate()的一个参数与两个参数的区别: @Override public void onCreate(Bu ...

  3. AC日记——字符串的展开 openjudge 1.7 35

    35:字符串的展开 总时间限制:  1000ms 内存限制:  65536kB 描述 在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h ...

  4. 关于OAUTH2.0的极品好文

    Web Server Flow: web ServerFlow是把oauth1.0的三个步骤缩略为两个步骤 首先这个是适合有server的第三方使用的. 1客户端http请求authorize 2服务 ...

  5. PHP的文件操作常用函数

    PHP文件操作 1 获得文件名:basename - 返回路径中的文件名部分 给出一个包含有指向一个文件的全路径的字符串,本函数返回基本的文件名.如果文件名是以 suffix 结束的,那这一部分也会被 ...

  6. Android中常用的布局

    一般分为5大类. Android中所有的空间第一字母都是大写 1.线性布局 LinearLayout 2.相对布局 RelativeLayout 3.帧布局--分层显示  FrameLayout 4. ...

  7. 开发之UI篇

    首先这里介绍一个软件一个插件,它们的主要功能是方便开发者看UI(如尺寸,颜色,大小等),两个配合使用 一. Sketch软件 1.Sketch  看ui图,还可以切图 2.Sketch 如何切图: 1 ...

  8. document.readyState等属性

    document.readyState:判断文档是否加载完成.firefox不支持. 这个属性是只读的,传回值有以下的可能: 0-UNINITIALIZED:XML 对象被产生,但没有任何文件被加载. ...

  9. c++ 头文件

    可以将程序分为二部分: 头文件:包含结构声明和使用这些结构的函数的原型 源代码文件: 包含与结构有关的函数的代码 不要将函数的定义或变量的声明放在头文件里, 一般头文件可以包含以下内容 >函数原 ...

  10. 求解最大正方形面积 — leetcode 221. Maximal Square

    本来也想像园友一样,写一篇总结告别 2015,或者说告别即将过去的羊年,但是过去一年发生的事情,实在是出乎平常人的想象,也不具有代表性,于是计划在今年 6 月份写一篇 "半年总结" ...