[LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会

题意

给定一个长度为 \(n\) 的字符串 \(s\), 对于所有 \(r\in[1,n]\) 求出 \(s\) 的所有LCP不小于 \(r\) 的后缀对的个数以及这些后缀对所能组成的最大权值.

一个后缀对 \((a,b)\) 的权值是它们左端点的权值的积.

\(n\le 3\times 10^5\).

题解

很久以前写的SAM沙雕题

因为要求LCP所以我们把这个串reverse一下用SAM搞.

根据后缀自动机的性质, 某两个后缀的LCP就是它们在SAM上对应结点的LCA的 \(len\).

那么对于计数的部分, 我们显然只要对于每个点都算出有多少个后缀以它为LCA就可以了.

后面求最大权值的部分看上去好像只要记录一下子树中的最大值和次大值就可以了, 然而权值可能有负数于是还得记录最小值和次小值.

计算出每个 \(len\) 的贡献后取后缀和就可以出答案了.

参考代码

  1. #include <bits/stdc++.h>
  2. const int MAXN=6e5+10;
  3. typedef long long int64;
  4. struct Edge{
  5. int from;
  6. int to;
  7. Edge* next;
  8. };
  9. Edge E[MAXN];
  10. Edge* head[MAXN];
  11. Edge* top=E;
  12. int n;
  13. int cnt=1;
  14. int root=1;
  15. int last=1;
  16. int v[MAXN];
  17. char s[MAXN];
  18. int len[MAXN];
  19. int prt[MAXN];
  20. int val[MAXN];
  21. int size[MAXN];
  22. int64 ans[MAXN];
  23. int64 sum[MAXN];
  24. int maxv[MAXN][2];
  25. int minv[MAXN][2];
  26. std::map<char,int> chd[MAXN];
  27. void DFS(int);
  28. void Insert(int,int);
  29. void Extend(char,int);
  30. int main(){
  31. memset(ans,0x80,sizeof(ans));
  32. memset(maxv,0x80,sizeof(maxv));
  33. memset(minv,0x7F,sizeof(minv));
  34. scanf("%d",&n);
  35. scanf("%s",s);
  36. for(int i=0;i<n;i++)
  37. scanf("%d",v+i);
  38. for(int i=1;i<=n;i++)
  39. Extend(s[n-i],v[n-i]);
  40. for(int i=2;i<=cnt;i++)
  41. Insert(prt[i],i);
  42. DFS(root);
  43. for(int i=n-1;i>=0;i--){
  44. sum[i]+=sum[i+1];
  45. ans[i]=std::max(ans[i],ans[i+1]);
  46. }
  47. for(int i=0;i<n;i++)
  48. printf("%lld %lld\n",sum[i],sum[i]==0?0:ans[i]);
  49. return 0;
  50. }
  51. void UpdateMax(int x,int v){
  52. maxv[x][1]=std::max(maxv[x][1],v);;
  53. if(maxv[x][0]<maxv[x][1])
  54. std::swap(maxv[x][0],maxv[x][1]);
  55. }
  56. void UpdateMin(int x,int v){
  57. minv[x][1]=std::min(minv[x][1],v);
  58. if(minv[x][0]>minv[x][1])
  59. std::swap(minv[x][0],minv[x][1]);
  60. }
  61. void DFS(int root){
  62. for(Edge* i=head[root];i!=NULL;i=i->next){
  63. DFS(i->to);
  64. sum[len[root]]+=1ll*size[root]*size[i->to];
  65. size[root]+=size[i->to];
  66. UpdateMin(root,minv[i->to][0]);
  67. UpdateMin(root,minv[i->to][1]);
  68. UpdateMax(root,maxv[i->to][0]);
  69. UpdateMax(root,maxv[i->to][1]);
  70. }
  71. if(size[root]>1)
  72. ans[len[root]]=std::max(ans[len[root]],std::max(1ll*minv[root][0]*minv[root][1],1ll*maxv[root][0]*maxv[root][1]));
  73. }
  74. void Extend(char x,int v){
  75. int p=last;
  76. int np=++cnt;
  77. size[last=np]=1;
  78. len[np]=len[p]+1;
  79. minv[np][0]=v;
  80. maxv[np][0]=v;
  81. while(p&&!chd[p].count(x))
  82. chd[p][x]=np,p=prt[p];
  83. if(p==0)
  84. prt[np]=root;
  85. else{
  86. int q=chd[p][x];
  87. if(len[q]==len[p]+1)
  88. prt[np]=q;
  89. else{
  90. int nq=++cnt;
  91. chd[nq]=chd[q];
  92. prt[nq]=prt[q];
  93. prt[q]=nq;
  94. prt[np]=nq;
  95. len[nq]=len[p]+1;
  96. while(p&&chd[p][x]==q)
  97. chd[p][x]=nq,p=prt[p];
  98. }
  99. }
  100. }
  101. void Insert(int from,int to){
  102. top->from=from;
  103. top->to=to;
  104. top->next=head[from];
  105. head[from]=top++;
  106. }

[LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会的更多相关文章

  1. bzoj 4199 && NOI 2015 品酒大会

    一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainbow 调制了 ...

  2. [LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机

    [LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机 题意 给定平面上的 \(n\) 个整点 \((x_i,y_i)\), 一共有两个问题. 第一个问题是从原 ...

  3. [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程

    [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程 题意 给定一张无向图, 每条边有一个距离和一个高度. 再给定 \(q\) 组可能在线的询问, 每组询问给定一个点 ...

  4. [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分

    [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分 题意 给定一个字符串 \(S\), 求有多少种将 \(S\) 的子串拆分为形如 AABB 的拆分方案 \(| ...

  5. [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士

    [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...

  6. UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)

    水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.org/problemnew/show/P2178 https://www.lydsy.com/JudgeOnline ...

  7. 【UOJ #131】【NOI 2015】品酒大会

    http://uoj.ac/problem/131 求出后缀数组和height数组后,从大到小扫相似度进行合并,每次相当于合并两个紧挨着的区间. 合并区间可以用并查集来实现,每个区间的信息都记录在这个 ...

  8. uoj 131/bzoj 4199 [NOI2015]品酒大会 后缀树+树d

    题目大意 见uoj131 分析 题目的提示还是很明显的 \(r\)相似就就代表了\(0...r-1\)相似 建出后缀树我们能dfs算出答案 再后缀和更新一下即可 注意 细节挺多的,但数据很良心 不然我 ...

  9. [NOI 2015]品酒大会

    Description 题库链接 \(n\) 杯鸡尾酒排成一行,其中第 \(i\) 杯酒 (\(1 \leq i \leq n\)) 被贴上了一个标签 \(s_i\),每个标签都是 \(26\) 个小 ...

随机推荐

  1. 用canvas实现手写签名功能

    最近开发网站有一个需求,要求页面上有一块区域,用户能用鼠标在上面写字,并能保存成图片 base64 码放在服务器.这样的需求用 canvas 实现是最好的.需要用到 canvas 的以下几个属性: b ...

  2. Educational Codeforces Round 76 (Rated for Div. 2) C. Dominated Subarray 水题

    C. Dominated Subarray Let's call an array

  3. C#开发BIMFACE系列15 服务端API之获取模型的View token

    系列目录     [已更新最新开发文章,点击查看详细] 在<C#开发BIMFACE系列3 服务端API之获取应用访问凭证AccessToken>中详细介绍了应用程序访问API的令牌凭证.我 ...

  4. [java 基础]反射入门

    原文 概况 使用java的反射,可以让我们检查(或者修改)类,接口,字段,方法的特性.当你在编译期不知道他们的名字的时候非常有用. 除此之外,可以使用反射来创建实例,调用方法或者get/set 字段值 ...

  5. pixijs shader fade 从左到有右淡入 从下到上淡入效果

    pixijs shader fade 从左到有右淡入     从下到上淡入效果 const app = new PIXI.Application({ transparent: true }); doc ...

  6. [Ljava.lang.String是一个字符串数组的字节码表示

    打印一个字符串数组的话,会发现 String[] arr = new String[10]; // String[] arr = {"yanggb", "huangq&q ...

  7. WebSocket数据加密——AES与RSA混合加密

    前言 之前在写“一套简单的web即时通讯”,写到第三版的时候没什么思路,正好微信公众号看到一篇讲API交互加密,于是就自己搞了一套AES与RSA混合加密,无意中产生应用在WebSocket想法,好在思 ...

  8. node.js的async和await

    一.async和await是什么 ES2017 标准引入了 async 函数,使得异步操作变得更加方便,async其实本质是Generator函数的语法糖 async表示函数里有异步操作 await表 ...

  9. Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理

    Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理 说明:Java生鲜电商平台中,我们将进一步理解微服务架构的核心要点和实现原理,为读者的实践提供微服务的设计模式,以期让微服务 ...

  10. MAC TXT文本

    Mac系统下.txt格式的纯文本怎么保存? 作者:佚名 字体:[增加 减小] 来源:互联网 时间:06-02 14:29:23 我要评论 Mac系统下.txt格式的纯文本怎么保存?.txt是个用途广泛 ...