【[AHOI2013]差异】
这个题一看就是为后缀家族设计的
我们看到我们要求的这个柿子
\]
显然的是前面的那些东西是个定值
就是保证每一个长度都会被其他长度算到,也就是算到\(n-1\)次
于是把前面那些东西拿出来就是
\]
之后再看后面那些东西
所有后缀的\(lcp\)的长度?
先来考虑一下如何求两个后缀的\(lcp\)
哈希+二分啊\(SA\)啊
对于后缀\(i,j\),他们的\(lcp\)长度就是\(min(heighht[rk[i]+1]...height[rk[j]])\)
于是现在的问题转化为求出\(height\)数组所有子区间的最小值的和
我们可以考虑一个动态往序列末尾加数的过程
也就是我们往末尾加一个数都会和之前所有的数形成一个新的区间
考虑快速算出这些区间的最小值的和
我们可以对每一个数存储一个\(a_i\),表示\(i\)到当前序列末尾的最小值是多少
我们每次加入一个数可以对更新一下所有的\(a_i\),把所有比当前加入的数大的\(a_i\)变成当前数就好了
这不就\(T\)了吗
我们发现我们只需要求出所有\(a_i\)的和,并不需要关心这个\(i\)来自哪里,于是我们可以把相等的\(a_i\)放在一起计算,也就是每次新加入一个数就暴力扫一遍把那些比当前加入数大的合并到一个\(a_i\)里
看起来复杂度并不科学,但是最坏情况下就相当于是一个线段树的复杂度了,\(O(n)\)的,跑的还挺快的
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define maxn 500005
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define pt putchar(1)
inline int read()
{
char c=getchar();int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int n,m,top;
LL ans=0,sum=0;
char S[maxn];
int tax[maxn],sa[maxn],rk[maxn],tp[maxn],height[maxn];
int L[maxn],R[maxn],st[maxn];
int a[maxn],cnt[maxn];
LL pre[maxn];
inline void qsort()
{
for(re int i=0;i<=m;i++) tax[i]=0;
for(re int i=1;i<=n;i++) tax[rk[i]]++;
for(re int i=1;i<=m;i++) tax[i]+=tax[i-1];
for(re int i=n;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
}
int main()
{
scanf("%s",S+1);
n=strlen(S+1);
m=75;
for(re int i=1;i<=n;i++) rk[i]=S[i]-'a'+1,tp[i]=i;
qsort();
for(re int w=1,p=0;p<n;m=p,w<<=1)
{
p=0;
for(re int i=1;i<=w;i++) tp[++p]=n-w+i;
for(re int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
qsort();
for(re int i=1;i<=n;i++) std::swap(tp[i],rk[i]);
rk[sa[1]]=p=1;
for(re int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
}
int k=0;
for(re int i=1;i<=n;i++)
{
if(k) --k;
int j=sa[rk[i]-1];
while(S[i+k]==S[j+k]) ++k;
height[rk[i]]=k;
}
ans+=height[2];
a[1]=ans;cnt[1]=1,sum=ans;
top=1;
for(re int i=3;i<=n;i++)
{
int now=1;
while(top&&height[i]<=a[top])
now+=cnt[top],sum-=a[top]*cnt[top],top--;
cnt[++top]=now;
a[top]=height[i];
sum+=cnt[top]*a[top];
ans+=sum;
}
printf("%lld\n",(LL)(n-1)*(LL)(n+1)*(LL)n/2ll-2ll*ans);
return 0;
}
【[AHOI2013]差异】的更多相关文章
- BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2326 Solved: 1054[Submit][Status ...
- bzoj 3238 Ahoi2013 差异
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2357 Solved: 1067[Submit][Status ...
- BZOJ 3238: [Ahoi2013]差异 [后缀自动机]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2512 Solved: 1140[Submit][Status ...
- BZOJ_3238_[Ahoi2013]差异_后缀自动机
BZOJ_3238_[Ahoi2013]差异_后缀自动机 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sam ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- 【LG4248】[AHOI2013]差异
[LG4248][AHOI2013]差异 题面 洛谷 题解 后缀数组版做法戳我 我们将原串\(reverse\),根据后缀自动机的性质,两个后缀的\(lcp\)一定是我们在反串后两个前缀的\(lca\ ...
- 【BZOJ3238】[AHOI2013]差异
[BZOJ3238][AHOI2013]差异 题面 给定字符串\(S\),令\(T_i\)表示以它从第\(i\)个字符开始的后缀.求 \[ \sum_{1\leq i<j\leq n}len(T ...
- P4248 [AHOI2013]差异 解题报告
P4248 [AHOI2013]差异 题目描述 给定一个长度为 \(n\) 的字符串 \(S\),令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀.求 \[\displaystyle \s ...
- 【BZOJ 3238】 3238: [Ahoi2013]差异(SAM)
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3047 Solved: 1375 Description In ...
- bzoj 3238: [Ahoi2013]差异 -- 后缀数组
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个 ...
随机推荐
- Stack源码解析
我们从一个DEMO作为入口,了解Java的Stack的源码,代码如: Stack<String> stack = new Stack<>(); stack.push(" ...
- 数据结构与算法--最短路径之Bellman算法、SPFA算法
数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...
- 类(class)相关概念小结
参考在线文档,整理php中类的相关概念如下 $this 在类的内部可以使用伪变量$this,这个伪变量为一个到主叫对象(经个人测试理解这应该是在运行时的真实对象,不是类,运行时绑定)的引用,所以一 ...
- 本地服务器搭建服务:mysql
话不多少,mysql的优劣不再此讨论. 1.官网地址:https://dev.mysql.com/downloads/mysql/ 下载页面直接 No thanks,just start my do ...
- 查看linux 内存
1.vmstat vmstat命令显示实时的和平均的统计,覆盖CPU.内存.I/O等内容.例如内存情况,不仅显示物理内存,也统计虚拟内存. $ vmstat -s 2.top top命令提供了实时的运 ...
- 一步步弄懂HTTPS
为什么要使用HTTPS? HTTP采用明文传输,存在被监听.内容被篡改.身份被冒充的可能.为了保证安全性,需要对数据进行加密,这便有了HTTPS. 一步步分析HTTPS 1. 采用哪种加密方式加密数据 ...
- CentOS7安装maven3.6.1
1.下载maven的tar.gz安装包 2.移到centos7中并解压 tar -xzvf maven.tar.gz 3.开始配置maven环境变量,通过命令 vim /etc/profile 4.配 ...
- bootstrap datetimepicker日期插件美化
效果 https://segmentfault.com/img/bVbieIp?w=1029&h=461 原文链接:https://segmentfault.com/a/11900000167 ...
- HTTP 协议入门-笔记
原文参考http://mp.weixin.qq.com/s/czx0AHaItrJ-c49XDboIUg HTTP是基于TCP/IP协议的应用层协议,规定了客户端和服务端之间的通信格式,默认使用80 ...
- JS原生添加删除class的方法
之前习惯了使用jquery的addClass的方法,然后就去找了下别人写的代码. [javascript] view plain copy function hasClass(obj,cls) { r ...