题目链接

思路

观察题目中的式子,可以发现前两项是定值。所以只需要求出最后一项就行了。

然后题目就转化为了求字符串中所有后缀的\(lcp\)长度之和。

可以想到用后缀数组。在后缀数组上两个后缀的\(lcp\)长度表现为两个后缀排名之间的\(height\)的最小值。

所以现在问题就又转化为了在\(height\)数组上求所有区间最小值之和。

这个可以用单调栈做到。

代码

  1. /*
  2. * @Author: wxyww
  3. * @Date: 2019-01-30 19:14:49
  4. * @Last Modified time: 2019-01-30 20:49:38
  5. */
  6. #include<cstdio>
  7. #include<iostream>
  8. #include<cstdlib>
  9. #include<cstring>
  10. #include<cmath>
  11. #include<ctime>
  12. #include<bitset>
  13. using namespace std;
  14. typedef long long ll;
  15. #define int ll
  16. const int N = 500010;
  17. ll read() {
  18. ll x=0,f=1;char c=getchar();
  19. while(c<'0'||c>'9') {
  20. if(c=='-') f=-1;
  21. c=getchar();
  22. }
  23. while(c>='0'&&c<='9') {
  24. x=x*10+c-'0';
  25. c=getchar();
  26. }
  27. return x*f;
  28. }
  29. int sa[N],rk[N],height[N],c[N],x[N],y[N];
  30. char s[N];
  31. int m,n;
  32. void get_sa() {
  33. for(int i = 1;i <= m;++i) c[i] = 0;
  34. for(int i = 1;i <= n;++i) ++c[x[i] = s[i]];
  35. for(int i = 2;i <= m;++i) c[i] += c[i - 1];
  36. for(int i = n;i >= 1;--i) sa[c[x[i]]--] = i;
  37. for(int k = 1;k <= n;k <<= 1) {
  38. int num = 0;
  39. for(int i = n - k + 1;i <= n; ++i) y[++num] = i;
  40. for(int i = 1;i <= n;++i) if(sa[i] > k) y[++num] = sa[i] - k;
  41. for(int i = 2;i <= m;++i) c[i] = 0;
  42. for(int i = 1;i <= n;++i) ++c[x[i]];
  43. for(int i = 1;i <= m;++i) c[i] += c[i - 1];
  44. for(int i = n;i >= 1;--i) sa[c[x[y[i]]]--] = y[i];
  45. swap(x,y);
  46. num = 0;
  47. x[sa[1]] = ++num;
  48. for(int i = 2;i <= n;++i) {
  49. if(y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) x[sa[i]] = num;
  50. else x[sa[i]] = ++num;
  51. }
  52. if(num == n) break;
  53. m = num;
  54. }
  55. }
  56. int h[N],q[N],tail;
  57. void get_height() {
  58. for(int i = 1;i <= n;++i) rk[sa[i]] = i;
  59. int k = 0;
  60. for(int i = 1;i <= n;++i) {
  61. if(rk[i] == 1) continue;
  62. if(k) --k;
  63. int j = sa[rk[i] - 1];
  64. while(j + k <= n && i + k <= n && s[j + k] == s[i + k]) ++k;
  65. h[i] = height[rk[i]] = k;
  66. }
  67. }
  68. ll work() {
  69. int tail = 0;
  70. ll now = 0,ans = 0;
  71. for(int i = 1; i <= n;++i) {
  72. while(height[i] < height[q[tail]] && tail) now -= height[q[tail]] * (q[tail] - q[tail - 1]),tail--;
  73. q[++tail] = i;
  74. now += height[i] * (q[tail] - q[tail - 1]);
  75. ans += now;
  76. }
  77. return ans;
  78. }
  79. int get(int x,int y) {
  80. int ans = 1e9;
  81. int l = min(rk[x],rk[y]),r = max(rk[x],rk[y]);
  82. for(int i = l + 1;i <= r;++i) ans = min(ans,height[i]);
  83. return ans;
  84. }
  85. signed main() {
  86. scanf("%s",s + 1);
  87. n = strlen(s + 1);
  88. m = 'z';
  89. get_sa();
  90. get_height();
  91. ll ans = 0;
  92. for(int i = 1;i <= n;++i)
  93. ans += i * (i - 1) + i * (n - i);
  94. ll LC = 2ll * work();
  95. cout<<ans - LC;
  96. return 0;
  97. }

bzoj3238 差异的更多相关文章

  1. [bzoj3238]差异(后缀数组+单调栈)

    显然我们可以先把len(Ti)+len(Tj)的值先算出来,再把LCP减去.所有len(Ti)+len(Tj)的值为n*(n-1)*(n+1)/2,这个随便在纸上画一画就可以算出来的. 接下来问题就是 ...

  2. 【BZOJ3238】差异(后缀自动机)

    [BZOJ3238]差异(后缀自动机) 题面 BZOJ 题解 前面的东西直接暴力算就行了 其实没必要算的正正好 为了方便的后面的计算 我们不考虑\(i,j\)的顺序问题 也就是先求出\(\sum_{i ...

  3. 【BZOJ3238】[AHOI2013]差异

    [BZOJ3238][AHOI2013]差异 题面 给定字符串\(S\),令\(T_i\)表示以它从第\(i\)个字符开始的后缀.求 \[ \sum_{1\leq i<j\leq n}len(T ...

  4. 【BZOJ3238】[Ahoi2013]差异 后缀数组+单调栈

    [BZOJ3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...

  5. bzoj3238 [Ahoi2013]差异 后缀数组+单调栈

    [bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...

  6. [bzoj3238][Ahoi2013]差异_后缀数组_单调栈

    差异 bzoj-3238 Ahoi-2013 题目大意:求任意两个后缀之间的$LCP$的和. 注释:$1\le length \le 5\cdot 10^5$. 想法: 两个后缀之间的$LCP$和显然 ...

  7. BZOJ3238 [Ahoi2013]差异 【SAM or SA】

    BZOJ3238 [Ahoi2013]差异 给定一个串,问其任意两个后缀的最长公共前缀长度的和 1.又是后缀,又是\(lcp\),很显然直接拿\(SA\)的\(height\)数组搞就好了,配合一下单 ...

  8. 【BZOJ-3238】差异 后缀数组 + 单调栈

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

  9. 【bzoj3238】 Ahoi2013—差异

    http://www.lydsy.com/JudgeOnline/problem.php?id=3238 (题目链接) 题意 给出一个字符串,求${\sum_{1<=i<j<=n} ...

随机推荐

  1. MyBatis映射文件5

    返回map     Map<String,Object> getEmpByResMap(Integer id); <select id="getEmpByResMap&qu ...

  2. re正则表达式-1

    匹配/查找/替换/分割函数: import re re.match('aa','aabbcc') 返回对象中span为开始位置和结束位置 re.match('aa','bbaacc') #返回值为No ...

  3. MCV 和 MTV框架基本信息

    一 . MCV # web服务器开发最著名的MVC模式 M : model.py 就是和数据库打交道的, 创建表等操作 V : view 视图(视图函数,就是装HTML文件的) C : control ...

  4. Partition算法以及其应用详解上(Golang实现)

    最近像在看闲书一样在看一本<啊哈!算法> 当时在amazon上面闲逛挑书,看到巨多人推荐这本算法书,说深入浅出简单易懂便买来阅读.实际上作者描述算法的能力的确令人佩服.就当复习常用算法吧. ...

  5. 学习 Spring (六) 自动装配

    Spring入门篇 学习笔记 No: (默认)不做任何操作 byName: 根据属性名自动装配.此选项将检查容器并根据名字查找与属性完全一致的 bean,并将其与属性自动装配 byType: 如果容器 ...

  6. 人工智能将继续壮大,两会委员建议增加“AI+教育”支持板块

    导读 今年上海两会期间,上海市政协委员.上海交通大学机械与动力工程学院教授范秀敏提交提案,建议政府在推进上海人工智能专项建设中,增加“AI+教育”专项支持板块,并鼓励集聚发展AI产业的各个区,在人工智 ...

  7. django中怎么使用自定义管理后台xadmin

    django中怎么使用自定义管理后台xadmin 2018年05月19日 15:48:08 LH_python 阅读数:1001   首先创建基本的django项目,配置好基本的model ,url, ...

  8. DRF 版本和认证

    Django Rest Framework 版本控制组件 DRF的版本 版本控制是做什么用的, 我们为什么要用 首先我们要知道我们的版本是干嘛用的呢~~大家都知道我们开发项目是有多个版本的~~ 当我们 ...

  9. 【XSY1519】彩灯节 DP 数学 第二类斯特林数

    题目大意 ​ 有\(n\)盏灯,\(m\)个限制.每个限制\((x,y)\)表示第\(x\)盏灯与第\(y\)盏灯之间必须且只能亮一盏. ​ 记一种情况\(x\)亮着的灯的数量为\(f_x\),求\( ...

  10. 使用IDEA部署项目到远程服务器

    1.选择Tools -> Deployment -> Configuration... 2.配置连接信息,Linux服务器一般都选择SFTP 3.配置本地上传文件路径.远程上传文件路径 4 ...