正题

题目链接:https://www.ybtoj.com.cn/problem/532


题目大意

给出\(n\)个点的一个\(Trie\)树,定义\(S_x\)表示节点\(x\)代表的字符串

求$$max{|LCP(S_x,S_y)|+|LCS(S_x,S_y)|}(x\neq y)$$

(\(LCP/LCS\)分别表示最长公共前/后缀)

\(1\leq n\leq 2\times 10^5\)


解题思路

正解好像是树上\(SA\)+线段树合并的做法可是我不会,就写了广义\(SAM\)

\(SAM\)的\(parents\)树就是后缀树,这里给出了\(Trie\)树就是一个构造广义\(SAM\)的好条件。

构造出来的广义\(SAM\)上的\(parents\)树上的\(LCA\)的\(len\)就是两个串的\(LCS\)。

\(Trie\)树上的\(LCA\)深度就是两个串的\(LCP\)。

考虑枚举\(Trie\)树上的一个点\(x\),求它的子树中\(LCS\)最大的一个点对,也就是后缀树上\(LCA\)最深。

对后缀树求一个\(dfs\)序,那么最优的点对都只会出现在相邻的点对中,这样的点对数量不会很多,可以考虑一种枚举的方法。

可以使用线段树合并,然后合并的时候每个节点维护一个改区间内最左/右的值。然后拿左区间的最右值和右区间的最左值计算答案就好了。

时间复杂度\(O(n\log^2n)\),如果肯写\(ST\)表求\(LCA\)可以做到\(O(n\log n)\)


code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<vector>
  5. #include<map>
  6. using namespace std;
  7. const int N=4e5+10,T=20,M=N<<5;
  8. struct node{
  9. int to,next,w;
  10. }a[N];
  11. int n,tot,cnt,ans,ls[N],len[N],fa[N],f[N][T+1];
  12. int rfn[N],dfn[N],g[N],rt[N],dep[N],p[N];
  13. vector<int>G[N];map<int,int>ch[N];
  14. void addl(int x,int y,int w){
  15. a[++tot].to=y;
  16. a[tot].next=ls[x];
  17. ls[x]=tot;a[tot].w=w;
  18. return;
  19. }
  20. int Insert(int p,int c){
  21. int np=++cnt;len[np]=len[p]+1;
  22. for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
  23. if(!p)fa[np]=1;
  24. else{
  25. int q=ch[p][c];
  26. if(len[p]+1==len[q])fa[np]=q;
  27. else{
  28. int nq=++cnt;ch[nq]=ch[q];
  29. len[nq]=len[p]+1;fa[nq]=fa[q];
  30. fa[np]=fa[q]=nq;
  31. for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
  32. }
  33. }
  34. return np;
  35. }
  36. void dfs(int x){
  37. for(int i=ls[x];i;i=a[i].next){
  38. int y=a[i].to;
  39. p[y]=Insert(p[x],a[i].w);
  40. dfs(y);
  41. }
  42. return;
  43. }
  44. void dfs2(int x){
  45. dfn[++cnt]=x;rfn[x]=cnt;
  46. for(int i=0;i<G[x].size();i++){
  47. dep[G[x][i]]=dep[x]+1;
  48. dfs2(G[x][i]);
  49. }
  50. return;
  51. }
  52. int LCA(int x,int y){
  53. x=dfn[x];y=dfn[y];
  54. if(dep[x]>dep[y])swap(x,y);
  55. for(int i=T;i>=0;i--)
  56. if(dep[f[y][i]]>=dep[x])
  57. y=f[y][i];
  58. if(x==y)return x;
  59. for(int i=T;i>=0;i--)
  60. if(f[x][i]!=f[y][i])
  61. x=f[x][i],y=f[y][i];
  62. return f[x][0];
  63. }
  64. struct SegTree{
  65. int cnt,ls[M],rs[M],l[M],r[M];
  66. void Change(int &x,int L,int R,int pos){
  67. if(!x)x=++cnt;l[x]=r[x]=pos;
  68. if(L==R)return;
  69. int mid=(L+R)>>1;
  70. if(pos<=mid)Change(ls[x],L,mid,pos);
  71. else Change(rs[x],mid+1,R,pos);
  72. return;
  73. }
  74. int Merge(int &x,int y,int L,int R){
  75. if(!x||!y){x=x|y;return 0;}
  76. int mid=(L+R)>>1,ans=0;
  77. ans=Merge(ls[x],ls[y],L,mid);
  78. ans=max(ans,Merge(rs[x],rs[y],mid+1,R));
  79. l[x]=ls[x]?l[ls[x]]:l[rs[x]];
  80. r[x]=rs[x]?r[rs[x]]:r[ls[x]];
  81. if(ls[x]&&rs[x])ans=max(ans,len[LCA(r[ls[x]],l[rs[x]])]);
  82. return ans;
  83. }
  84. }Tr;
  85. void dfs3(int x,int dep){
  86. Tr.Change(rt[x],1,cnt,rfn[p[x]]);
  87. for(int i=ls[x];i;i=a[i].next){
  88. int y=a[i].to;
  89. dfs3(y,dep+1);
  90. g[x]=max(g[x],g[y]);
  91. g[x]=max(g[x],Tr.Merge(rt[x],rt[y],1,cnt));
  92. }
  93. ans=max(ans,g[x]+dep);
  94. return;
  95. }
  96. int main()
  97. {
  98. freopen("recollection.in","r",stdin);
  99. freopen("recollection.out","w",stdout);
  100. scanf("%d",&n);
  101. for(int i=2;i<=n;i++){
  102. int x,w;
  103. scanf("%d%d",&x,&w);
  104. addl(x,i,w);
  105. }
  106. cnt=p[1]=1;dfs(1);
  107. for(int i=2;i<=cnt;i++)
  108. G[fa[i]].push_back(i),f[i][0]=fa[i];
  109. cnt=0;dfs2(1);
  110. for(int j=1;j<=T;j++)
  111. for(int i=1;i<=cnt;i++)
  112. f[i][j]=f[f[i][j-1]][j-1];
  113. dfs3(1,0);
  114. printf("%d\n",ans);
  115. }

YbtOJ#532-往事之树【广义SAM,线段树合并】的更多相关文章

  1. CodeForces - 666E: Forensic Examination (广义SAM 线段树合并)

    题意:给定字符串S,然后M个字符串T.Q次询问,每次给出(L,R,l,r),问S[l,r]在L到R这些T字符串中,在哪个串出现最多,以及次数. 思路:把所有串建立SAM,然后可以通过倍增走到[l,r] ...

  2. CF666E-Forensic Examination【广义SAM,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/CF666E 解题思路 给出一个串\(S\)和\(n\)个串\(T_i\).\(m\)次询问\(S_{a\sim b} ...

  3. CF204E-Little Elephant and Strings【广义SAM,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/CF204E 题目大意 \(n\)个字符串的一个字符串集合,对于每个字符串求有多少个子串是这个字符串集合中至少\(k\ ...

  4. bzoj1396识别子串(SAM+线段树)

    复习SAM板子啦!考前刷水有益身心健康当然这不是板子题/水题…… 很容易发现只在i位置出现的串一定是个前缀串.那么对答案的贡献分成两部分:一部分是len[x]-fa~len[x]的这部分贡献会是r-l ...

  5. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  6. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2271  Solved: 935[Submit][Stat ...

  7. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  8. hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  9. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

随机推荐

  1. tomcat9配置https-pfx

    下载tomcat9 wget https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-9/v9.0.37/bin/apache-tomcat-9.0.37.t ...

  2. EZpop分析

    首先源代码如下 <?php class Modifier { protected $var; public function append($value){ include($value); } ...

  3. docker ubuntu中文乱码

    docker ubuntu18.04 使用cat查看中文正常,使用vim查看中文乱码. 解决此问题需要修改"/etc/profile"文件. 1.修改前查看本地使用的语言环境: l ...

  4. C# .NetCore简单实现无限递归的功能

    1:在实际开发中,我们会经常使用到无限递归的情况,如菜单,父子级等的情况 2:Code 1 using System; 2 using System.Collections.Generic; 3 us ...

  5. Eclipse中安装配置Gradle

    Gradle是以Groovy语言为基础,面向Java应用为主.基于DSL(领域特定语言)语法的自动化构建工具. gradle对多工程的构建支持很出色,工程依赖是gradle的第一功能. gradle支 ...

  6. Charles-抓取https请求

    在未经设置之前,Charles是无法抓取https请求的,会出现unknown的标识.我们可以通过以下两步设置,解决该问题. 第一步:安装证书 https是在http的基础上加入ssl层,通过ssl来 ...

  7. VS dll 引用依赖

    在公司实习过程中,经常遇到三个问题: 开发环境 dll引用依赖 dll版本控制 一般公司都会配置开发/测试/Lab/线上四个环境,之后不管时开发什么项目,都与环境分不开边.这个和dll版本控制暂且记下 ...

  8. Mysql常用sql语句(5)- as 设置别名

    测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 需要注意,创建数据库和创建表的语句博文都在前面哦 整个 ...

  9. K8S_第一课作业_20200407

    (1)通过cgroup来限制memory ##消耗内存脚本 /tmp/xmem.sh #!/bin/bash mkdir /tmp/memory mount -t tmpfs -o size=2048 ...

  10. weblogic获取应用目录路径

    一.背景说明 在项目开发过程中,本地开发用的windows+tomcat,到了生产中,就成了linux+weblogic.部署工程后,应用报错,显示获取应用目录返回为null. 在网上查阅资料,发现在 ...