【[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 一行,一个 ...
随机推荐
- 使用 ajax 异步调用数据
ajax 脚本 <script type="text/javascript" > function show(page) { var xmlhttp; try { xm ...
- 在iframe窗体内 获取父级的元素;;在父窗口中获取iframe中的元素
在iframe中获取父窗口的元素 $(‘#父窗口中的元素ID’, parent.document).click(); 在父窗口中获取iframe中的元素 $(“#iframe的ID”).content ...
- (译文)The Linux Programming Interface:第1章(历史和标准)
1 HISTORY AND STANDARDS (译者:鱼时代 校对:fgn) Linux 是UNIX操作系统家族中的一员,在计算机出现以来,UNXI已经有很长的历史了.在这一章中的第一部分将对Un ...
- mongdb查询操作
1.db.table.find() 查询所有信息 db.table.findOne()查询第一个信息2.db.table.find({条件},{要显示列}) db.table.find({},{_id ...
- django admin登陆添加修改内容
model文件中 __all__ = ["Book", "Publisher", "Author"] from django.db impo ...
- grunt搭建自动化的web前端开发环境(转)
1. 前言 各位web前端开发人员,如果你现在还不知道grunt或者听说过.但是不会熟练使用grunt,那你就真的真的真的out了(三个“真的”重复,表示重点).至于grunt的作用,这里不详细说了, ...
- 微信小程序 引入公共页面的几种情况
1.不带参数 首先在pages文件夹中新建一个template文件夹,文件夹中新建一个template.wxml文件,代码如下 <!--template.wxml--> <templ ...
- JDK动态代理、CGLib动态代理
JDK动态代理源码 一.public static Object newProxyInstance ——> 调用下面这个方法二.Class<?> cl = getProxyClass ...
- Python 数据分析基础小结
一.数据读取 1.读写数据库数据 读取函数: pandas.read_sql_table(table_name, con, schema=None, index_col=None, coerce_fl ...
- 从零自学Java-5.使用条件测试进行判断
1.使用if语句进行最基本的条件测试:2.测试一个值大于还是小于另一个值:3.测试两个值是否相等:4.使用与if语句对应的else语句:5.组合多个条件测试:6.使用switch语句进行复杂的条件测试 ...