[BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】
题目链接:BZOJ - 3238
题目分析
显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显。
求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组。
那么我们可以用这个 Height 数组求出所有后缀之间 LCP 的和。
我们用 f[i] 表示字典序第 i 的后缀与字典序在 i 之后的所有后缀的 LCP 的和。
我们知道,两个后缀的 LCP 为 Height 数组中这两个后缀之间的最小值。
我们从最后向前推 i ,用一个单调栈维护后面的 Height 单调不上升,然后用 St[Top] 来推 f[i] 即可,具体见代码。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm> using namespace std; const int MaxL = 500000 + 5; typedef long long LL; LL Ans, Temp;
LL f[MaxL]; int n, Top;
int A[MaxL], Rank[MaxL], SA[MaxL], Height[MaxL], St[MaxL];
int VA[MaxL], VB[MaxL], VC[MaxL], Sum[MaxL]; char S[MaxL]; inline bool Cmp(int *a, int x, int y, int l) {
return (a[x] == a[y]) && (a[x + l] == a[y + l]);
} void DA(int *A, int n, int m) {
int *x, *y, *t;
x = VA; y = VB;
for (int i = 1; i <= m; ++i) Sum[i] = 0;
for (int i = 1; i <= n; ++i) ++Sum[x[i] = A[i]];
for (int i = 2; i <= m; ++i) Sum[i] += Sum[i - 1];
for (int i = n; i >= 1; --i) SA[Sum[x[i]]--] = i;
int p, q;
p = 0;
for (int j = 1; p < n; j <<= 1, m = p) {
q = 0;
for (int i = n - j + 1; i <= n; ++i) y[++q] = i;
for (int i = 1; i <= n; ++i) {
if (SA[i] <= j) continue;
y[++q] = SA[i] - j;
}
for (int i = 1; i <= m; ++i) Sum[i] = 0;
for (int i = 1; i <= n; ++i) VC[i] = x[y[i]];
for (int i = 1; i <= n; ++i) ++Sum[VC[i]];
for (int i = 2; i <= m; ++i) Sum[i] += Sum[i - 1];
for (int i = n; i >= 1; --i) SA[Sum[VC[i]]--] = y[i];
t = x; x = y; y = t; p = 1;
x[SA[1]] = 1;
for (int i = 2; i <= n; ++i)
x[SA[i]] = Cmp(y, SA[i], SA[i - 1], j) ? p : ++p;
}
for (int i = 1; i <= n; ++i) Rank[SA[i]] = i; //GetHeight
int h = 0, o;
for (int i = 1; i <= n; ++i) {
if (Rank[i] == 1) continue;
o = SA[Rank[i] - 1];
while (A[i + h] == A[o + h]) ++h;
Height[Rank[i]] = h;
if (h > 0) --h;
}
} int main()
{
scanf("%s", S + 1);
n = strlen(S + 1);
for (int i = 1; i <= n; ++i) A[i] = S[i] - 'a' + 1;
DA(A, n, 26);
Ans = 0ll; Temp = 0ll;
for (int i = 1; i <= n; ++i)
Ans += (LL)(n - i + 1) * (LL)(n - 1);
Top = 0;
St[++Top] = n + 1;
for (int i = n; i >= 2; --i) {
while (Top > 0 && Height[St[Top]] > Height[i]) --Top;
int x = St[Top];
f[i] = (LL)Height[i] + (LL)Height[i] * (x - i - 1) + (LL)f[x];
Temp += f[i];
St[++Top] = i;
}
Ans -= Temp * 2ll;
printf("%lld\n", Ans);
return 0;
}
[BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】的更多相关文章
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
- BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2326 Solved: 1054[Submit][Status ...
- 【BZOJ3238】[Ahoi2013]差异 后缀数组+单调栈
[BZOJ3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...
- [AHOI2013] 差异 - 后缀数组,单调栈
[AHOI2013] 差异 Description 求 \(\sum {len(T_i) + len(T_j) - 2 lcp(T_i,T_j)}\) 的值 其中 \(T_i (i = 1,2,... ...
- bzoj3238 [Ahoi2013]差异 后缀数组+单调栈
[bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】
题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...
- 【BZOJ3879】SvT 后缀数组+单调栈
[BZOJ3879]SvT Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干 ...
随机推荐
- 怎样安装两个tomcat,怎样配置
装两个tomcat 各自是6.0和7.0 可想执行tomcat6.0 可是实际上却执行tomcat7.0 两个版本号都是用解压缩包 事实上就是不能执行tomcat6.0 仅仅能执行7.0 两个环境变量 ...
- 实用技巧:简单而有用的nohup命令介绍(转)
简单而有用的nohup命令在UNIX/LINUX中,普通进程用&符号放到后台运行,如果启动该程序的控制台logout,则该进程随即终止. 要实现守护进程,一种方法是按守护进程的规则去编程(本站 ...
- OOP 概述
面向对象程序设计基于四个基本概念:数据抽象.封装.继承和动态绑定. 类的基本思想是数据抽象和封装. 1 数据抽象 数据抽象是一种依赖于接口和实现分离的编程技术.类的接口包括用户所能执行的操作:类的实现 ...
- Java——(五)Collection之List集合、ArrayList和Vector实现类
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.List集合 List集合代表一个元素有序.客重复的集合,集合中每个元素都有其对应的顺序索引 ...
- 【转载】ASP.NET支持多语言
ASP.NET 2.0中实现:1.使用工具自动生成本地化资源(LocalResources) 首先建立一个WEB工程,如图所示:双击Default.aspx,切换到[设计]视图,从工具箱里拖一个But ...
- 自己写的自动生成动态边框的jquery小插件
思路就是在元素四周添加<ul>列表,然后周期性地改变它的颜色,实现动态的效果,不支持ie7.ie8 预览链接http://gorey.sinaapp.com/myBorder/border ...
- 常用CDN公共库
Jquery <script src="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js"></scrip ...
- 介绍TableView非常不错的一篇文章
原文:http://blog.csdn.net/fanxiaochuan/article/details/11332775 介绍TableView非常不错的一篇文章: http://www.cocoa ...
- SGU 115.Calendar
连水3道,还能更水么... #include <stdio.h> using namespace std; ] = {, , , , , , , , , , , , }; int n, m ...
- SGU 118.Digital root
时间限制:0.25s 空间限制:4M 题目大意 给出n个数,求n1+n1*n2+n1*n2*n3+n1...nn 的数根,数根是一个数各个位置数字和的树根,个位数的数根为它本身. 例如,f[987]= ...