题意

给你一个长度为 \(n\) 的字符串,问 \(LCP(i,j)+(w_i\ xor\ w_j)\) 的最大值,其中 \(LCP\) 表示两个后缀的最长公共前缀。

\(n\le 10^5\)

分析

  • 建立 \(SA\) 之后把所有的 \(height\) 从大到小加入,维护连通块(类似 \(MST\) ),这样可以找到某个 \(height\) 作为两个后缀的 \(LCP\) 长度时的合法的区间,启发式合并 \(trie\) 即可。

  • 或者也可以建 \(SAM\) ,\(parent\) 树上启发式合并 \(trie\) 。

  • 总时间复杂度为 \(O(nlogn)\)。

    代码采用后缀数组的方式。

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. #define go(u) for(int i = head[u], v = e[i].to; i; i=e[i].lst, v=e[i].to)
  5. #define rep(i, a, b) for(int i = a; i <= b; ++i)
  6. #define pb push_back
  7. #define re(x) memset(x, 0, sizeof x)
  8. inline int gi() {
  9. int x = 0,f = 1;
  10. char ch = getchar();
  11. while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
  12. while(isdigit(ch)) { x = (x << 3) + (x << 1) + ch - 48; ch = getchar();}
  13. return x * f;
  14. }
  15. template <typename T> inline void Max(T &a, T b){if(a < b) a = b;}
  16. template <typename T> inline void Min(T &a, T b){if(a > b) a = b;}
  17. const int N = 1e5 + 7;
  18. int n, ans;
  19. char s[N];
  20. namespace SA {
  21. int sa[N], x[N], y[N], c[N], h[N];
  22. void pre(int m) {
  23. rep(i, 1, m) c[i] = 0;
  24. rep(i, 1, n) c[x[i] = s[i]] ++;
  25. rep(i, 1, m) c[i] += c[i - 1];
  26. for(int i = n; i; --i) sa[c[x[i]]--] = i;
  27. for(int k = 1; k <= n; k <<= 1) {
  28. int p = 0;
  29. for(int i = n; i >= n - k + 1; --i) y[++p] = i;
  30. rep(i, 1, n) if(sa[i] > k) y[++p] = sa[i] - k;
  31. rep(i, 1, m) c[i] = 0;
  32. rep(i, 1, n) c[x[y[i]]]++;
  33. rep(i, 1, m) c[i] += c[i - 1];
  34. for(int i = n; i; --i) sa[c[x[y[i]]]--] = y[i];
  35. swap(x, y);p = 1; x[sa[1]] = 1;
  36. rep(i, 2, n)
  37. x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++p;
  38. if(p >= n) break;m = p;
  39. }
  40. rep(i, 1, n) x[sa[i]] = i;
  41. for(int i = 1, j = 0; i <= n; ++i) {
  42. if(j) --j;if(sa[i] == 1) continue;
  43. while(s[i + j] == s[sa[x[i] - 1] + j]) ++j;
  44. h[x[i]] = j;
  45. }
  46. }
  47. }
  48. struct data {
  49. int p, h;
  50. bool operator <(const data &rhs) const {
  51. return h > rhs.h;
  52. }
  53. }t[N];
  54. int ndc;
  55. int par[N], rt[N], w[N], ch[N * 20][2];
  56. void ins(int v, int &rt) {
  57. if(!rt) rt = ++ndc;
  58. int u = rt;
  59. for(int i = 16; ~i; --i) {
  60. int c = v >> i & 1;
  61. if(!ch[u][c]) ch[u][c] = ++ndc;
  62. u = ch[u][c];
  63. }
  64. }
  65. int merge(int a, int b) {
  66. if(!a || !b) return a + b;
  67. rep(i, 0, 1) if(ch[a][i] || ch[b][i]) ch[a][i] = merge(ch[a][i], ch[b][i]);
  68. return a;
  69. }
  70. int getans(int dep, int a, int b) {
  71. int res = 0;
  72. rep(i, 0, 1) if(ch[a][i] && ch[b][i ^ 1]) Max(res, getans(dep - 1, ch[a][i], ch[b][i ^ 1]) + (1 << dep));
  73. if(res) return res;
  74. rep(i, 0, 1) if(ch[a][i] && ch[b][i]) Max(res, getans(dep - 1, ch[a][i], ch[b][i]));
  75. return res;
  76. }
  77. int getpar(int a) {
  78. return par[a] == a ? a: par[a] = getpar(par[a]);
  79. }
  80. void Union(int a, int b) {
  81. a = getpar(a), b = getpar(b);
  82. if(a == b) return;
  83. par[b] = a;
  84. rt[a] = merge(rt[a], rt[b]);
  85. }
  86. int main() {
  87. using namespace SA;
  88. n = gi();
  89. scanf("%s", s + 1);
  90. rep(i, 1, n) w[i] = gi();
  91. pre(128);
  92. rep(i, 2, n) t[i - 1] = (data){ i, h[i]};
  93. sort(t + 1, t + n);
  94. rep(i, 1, n) ins(w[sa[i]], rt[i]), par[i] = i;
  95. rep(i, 1, n - 1) {
  96. int f1 = getpar(t[i].p - 1), f2 = getpar(t[i].p), tmp = getans(16, rt[f1], rt[f2]);
  97. Max(ans, tmp + t[i].h);
  98. Union(f1, f2);
  99. }
  100. printf("%d\n", ans);
  101. return 0;
  102. }

[LOJ#6198]谢特[后缀数组+trie+并查集]的更多相关文章

  1. POJ1743 Musical Theme [后缀数组+分组/并查集]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

  2. BZOJ 4516: [Sdoi2016]生成魔咒——后缀数组、并查集

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4516 题意 一开始串为空,每次往串后面加一个字符,求本质不同的子串的个数,可以离线.即长度为 ...

  3. 【BZOJ4199&UOJ131】品酒大会(后缀数组,并查集)

    题意: 两杯“r相似” (r>1)的酒同时也是“1 相似”.“2 相似”.…….“(r−1) 相似”的. n<=300000 abs(a[i])<=10^9 思路:对于i,j两个后缀 ...

  4. 洛谷P4145 上帝造题的七分钟2/花神游历各国 [树状数组,并查集]

    题目传送门 题目背景 XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. 题目描述 "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是 ...

  5. loj6198谢特 后缀数组+并查集+Trie

    先把问题放在后缀数组上考虑 已知两个数组a b,求min(a[i],...,a[j])+(b[i]^b[j])的最大值 套路题 初始每个点都是一个小连通块 把a按从大到小的顺序加入,计算当前加入边作为 ...

  6. 谢特——后缀数组+tire 树

    题目 [题目描述] 由于你成功地在 $ \text{1 s} $ 内算出了上一题的答案,英雄们很高兴并邀请你加入了他们的游戏.然而进入游戏之后你才发现,英雄们打的游戏和你想象的并不一样…… 英雄们打的 ...

  7. [学习笔记]可持久化数据结构——数组、并查集、平衡树、Trie树

    可持久化:支持查询历史版本和在历史版本上修改 可持久化数组 主席树做即可. [模板]可持久化数组(可持久化线段树/平衡树) 可持久化并查集 可持久化并查集 主席树做即可. 要按秩合并.(路径压缩每次建 ...

  8. Colored Sticks - poj2513(trie + 并查集)

    问题便转化为:给定一个图,是否存在“一笔画”经过涂中每一点,以及经过每一边一次.这样就是求图中是否存在欧拉路Euler-Path.由图论知识可以知道,无向图存在欧拉路的充要条件为:① 图是连通的:② ...

  9. 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组

    涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...

随机推荐

  1. Oracle EBS OPM release step

    --release_step生产批 --created by jenrry SET serveroutput on DECLARE x_return_status VARCHAR2 (1); l_ex ...

  2. jmeter如何保持JSESSIONID

    利用Jmeter做接口测试的时候,如何提取头部的JSESSIONID然后传递到下一个请求,继续完成当前用户的请求. 一.如果响应数据里面没有返回JSESSIONID,直接添加http cookies ...

  3. 光杆mdf文件的导入

    场景,准备学习SSAS的时候,按照教程在微软下载了示例数据库AdventureWorksDW2012,下载来才发现只有一个mdf文件. 正好今天群里有位兄弟也碰到差不多的问题,客户数据库里的ldf文件 ...

  4. [SQLSERVER] [GPO] Add the Log on as a service Right to an Account

    Add the Log on as a service Right to an Account Updated: August 8, 2008 Applies To: Windows Server 2 ...

  5. C# 倒计时

    c#中有一个叫做timespan的数据类型,可以这样构造: TimeSpan ts = , , ); TimeSpan(hour,minute,second); 然后拖进去一个timer,叫timer ...

  6. kettle性能优化

    普通开发电脑,如果没有网络查询步骤,kettle正常的速度应该在3000~20000条/秒.如果速度在2000条/秒一下,就可能需要调优. 性能优化的方式包括如下几种: 1.通过改变开始复制的数量(针 ...

  7. Linux学习---linux下的彩蛋和各种有趣的命令

    [原文]https://www.toutiao.com/i6596596897392099844/ screenfetch 一个显示系统信息和主题信息的命令 使用方法 输入screenfetch 效果 ...

  8. Collection中的List,Set的toString()方法

    代码:     Collection c = new ArrayList();     c.add("hello");     c.add("world"); ...

  9. 3.2Python的循环结构语句:

    返回总目录 目录: 1.while循环 2.for循环 3.循环保留字:break与continue 循环总览: (一)while循环: (1)单个while循环: while 条件:     循环体 ...

  10. 某某D的手伸的实在太长了,路由器也未能幸免,致被阉割的TP-Link

    前段时间整了个服务器架上l2tp.server, TP-Link路由连上去后,全网走l2tp通道,而且不能配置相关的路由表 然后研究啊 找啊 查啊,确定是路由没有这功能 找客服问了一下,他一听就懂了, ...