题目传送门:洛谷 P4248

题意简述:

定义两个字符串 \(S\) 和 \(T\) 的差异 \(\operatorname{diff}(S,T)\) 为这两个串的长度之和减去两倍的这两个串的最长公共前缀的长度。

给定一个字符串,定义从第 \(i\) 个字符开始的后缀为 \(Suf_i\)。

求 \(\sum_{1\le i<j\le n}\operatorname{diff}(Suf_i,Suf_j)\)。

题解:

化简式子,原式等于

\[\begin{align*}&\left(\sum_{1\le i<j\le n}i+j\right)-2\times\sum_{1\le i<j\le n}\operatorname{lcp}(Suf_i,Suf_j)\\=& \frac{n(n-1)(n+1)}{2}-2\times\sum_{1\le i<j\le n}\operatorname{lcp}(Suf_i,Suf_j)\end{align*}\]

所以只要求出后半部分即可。

建立字符串的后缀数组。

考虑 Height 数组的贡献:Height 数组中 [2, n] 内的每一个区间都给答案贡献区间最小值。

套路:每个区间的区间最小值之和,使用单调栈解决。

  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. typedef long long LL;
  5. const int MN = ;
  6.  
  7. int N;
  8. char str[MN];
  9.  
  10. int M;
  11. int rk[MN], rk2[MN], SA[MN], SA2[MN];
  12. int buk[MN], cnt;
  13. int Height[MN];
  14.  
  15. void GetHeight() {
  16. int k = ;
  17. for (int i = ; i <= N; ++i) {
  18. if (rk[i] == ) { k = Height[] = ; continue; }
  19. if (k) --k;
  20. int j = SA[rk[i] - ];
  21. while (i + k <= N && j + k <= N && str[i + k] == str[j + k]) ++k;
  22. Height[rk[i]] = k;
  23. }
  24. }
  25.  
  26. void Rsort() {
  27. for (int i = ; i <= M; ++i) buk[i] = ;
  28. for (int i = ; i <= N; ++i) ++buk[rk[i]];
  29. for (int i = ; i <= M; ++i) buk[i] += buk[i - ];
  30. for (int i = N; i >= ; --i) SA[buk[rk[SA2[i]]]--] = SA2[i];
  31. }
  32.  
  33. void GetSA() {
  34. M = ;
  35. for (int i = ; i <= N; ++i) rk[i] = str[i] - 'a' + , SA2[i] = i;
  36. Rsort();
  37. for (int j = ; j < N; j <<= ) {
  38. int P = ;
  39. for (int i = N - j + ; i <= N; ++i) SA2[++P] = i;
  40. for (int i = ; i <= N; ++i) if (SA[i] > j) SA2[++P] = SA[i] - j;
  41. Rsort();
  42. rk2[SA[]] = P = ;
  43. for (int i = ; i <= N; ++i) {
  44. if (rk[SA[i]] != rk[SA[i - ]] || rk[SA[i] + j] != rk[SA[i - ] + j]) ++P;
  45. rk2[SA[i]] = P;
  46. }
  47. for (int i = ; i <= N; ++i) rk[i] = rk2[i];
  48. M = P;
  49. if (M == N) break;
  50. }
  51. GetHeight();
  52. }
  53.  
  54. int st[MN], t;
  55. int L[MN], R[MN];
  56.  
  57. int main() {
  58. scanf("%s", str + );
  59. N = strlen(str + );
  60. GetSA();
  61. st[t = ] = ;
  62. for (int i = ; i <= N; ++i) {
  63. while (t && Height[st[t]] > Height[i]) R[st[t--]] = i;
  64. L[i] = st[t];
  65. st[++t] = i;
  66. } while (t) R[st[t--]] = N + ;
  67. LL Ans = (LL)(N - ) * N * (N + ) / ;
  68. for (int i = ; i <= N; ++i)
  69. Ans -= 2ll * (R[i] - i) * (i - L[i]) * Height[i];
  70. printf("%lld\n", Ans);
  71. return ;
  72. }

洛谷 P4248: bzoj 3238: [AHOI2013]差异的更多相关文章

  1. 洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】

    可能是一个 SAM 常用技巧?感觉 SAM 的基础题好多啊.. 题目描述 给定一个长度为 \(n\) 的字符串 \(S\) ,令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀,求: \[ ...

  2. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

  3. bzoj 3238 Ahoi2013 差异

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2357  Solved: 1067[Submit][Status ...

  4. BZOJ 3238: [Ahoi2013]差异 [后缀自动机]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2512  Solved: 1140[Submit][Status ...

  5. bzoj 3238: [Ahoi2013]差异 -- 后缀数组

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个 ...

  6. ●BZOJ 3238 [Ahoi2013]差异

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3238 题解: 后缀数组套路深. 问题转化为求出任意两个后缀的LCP之和 在计算贡献时,各种不 ...

  7. BZOJ 3238 [Ahoi2013]差异(后缀自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3238 [题目大意] 给出一个串,设T[i]表示从第i位开始的后缀, 求sum(len( ...

  8. BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp

    http://www.lydsy.com/JudgeOnline/problem.php?id=3238 就算是全局变量,也不要忘记,初始化(吐血). 长得一副lca样,没想到是个树形dp(小丫头还有 ...

  9. BZOJ 3238: [Ahoi2013]差异((单调栈+后缀数组)/(后缀树))

    [传送门[(https://www.lydsy.com/JudgeOnline/problem.php?id=3238) 解题思路 首先原式可以把\(len\)那部分直接算出来,然后通过后缀数组求\( ...

随机推荐

  1. window.location.hash 使用

    [转]http://www.cnblogs.com/nifengs/p/5104763.html location是javascript里边管理地址栏的内置对象,比如location.href就管理页 ...

  2. PHP中测试in_array、isset、array_key_exists性能

    测试in_array.isset.array_key_exists性能.自己写的简易测试代码: ini_set('display_errors',true); error_reporting(E_AL ...

  3. TypeError: to_categorical() got an unexpected keyword argument 'nb_classes'

    在学习莫烦教程中keras教程时,报错:TypeError: to_categorical() got an unexpected keyword argument 'nb_classes',代码如下 ...

  4. PGM学习之六 从有向无环图(DAG)到贝叶斯网络(Bayesian Networks)

    本文的目的是记录一些在学习贝叶斯网络(Bayesian Networks)过程中遇到的基本问题.主要包括有向无环图(DAG),I-Maps,分解(Factorization),有向分割(d-Separ ...

  5. [NOI2016]旷野大计算

    Subtask0 造计算机神题.给一个忠告:珍爱生命,远离旷野大计算...... 代码在这里:戳我 Subtask1 给定\(a,b\):求\(-2a-2b\). 熟悉操作环境:\([-(a+b)]& ...

  6. 模板:CDQ分治

    UPD:18.06.15修正一些错误,感谢评论区巨佬orz CDQ分治不是一个顾名思义的东西,CDQ分治是为了纪念神犇陈丹琦而命名的一种算法. 那么CDQ分治能干什么?CDQ分治主要是用来解决一类”操 ...

  7. 一步步创建第一个Docker App —— 2. 创建 Docker化 主机

    原文:https://docs.docker.com/engine/getstarted-voting-app/node-setup/ 部署voting app的第一步,是为集群节点(swarm no ...

  8. Java之字节数组和字符串的转换问题

    今天在使用字节流复制图片的时候发现一个问题,就是将字节数组转化为字符串的时候会出现长度不同的问题.这其实是个错误的操作. public static void main(String[] args) ...

  9. android 7.0 新特性 和对开发者的影响

    android 7.0新特性 - jiabailong的专栏 - 博客频道 - CSDN.NEThttp://blog.csdn.net/jiabailong/article/details/5241 ...

  10. golang管道

    golang中的channel channel用于goroutine之间的通信 如果不用channel,使用共享全局变量的方式,需要加锁 // synchornized 同步 // golang中的 ...