bzoj3238
都LCP了很显然是要用到后缀数组的
显然前面的那个东西是可以直接算出来的
关键在于LCP的和怎么快速的计算
不难想到穷举height[i],然后判断这个height[i]可能成为多少对后缀的LCP
考虑到LCP(i,j)=min(height[rank[i]+1~rank[j]]) 假定rank[i]<rank[j];
假设height[l]是左边第一个小于height[i]的,height[r]是右边第一个小于height[i]的
则height[i]是(i-l)(r-i)对后缀的LCP
但这样有一个问题,相同height可能会被重复计算
为了避免重复,我们定义height[r]是右边第一个不大于height[i]的
这样就有两种方法来实现
第一种是二分+rmq,但不幸的是我竟然写超时,而且我觉得容易出错
第二种是利用单调队列,我们把height[i]对应的l,r定义为左右边界,记为l[i],r[i];
计算左边界和右边界是相似的,这里我们讨论左边界
假如height[j]<=height[k] (j>k) 那么对于之后的height[i],
要么能延伸到k之前(height[i]<=height[j]),要么只能左边界就是j(height[i]>height[j]),不用比较height[k]
显然我们要维护一个单调不降的队列就行了
最后计算的时候注意用int64
var rank,sa,y,q,x,sum,h,l,r:array[..] of longint;
s:ansistring;
i,n,m,p,j,t:longint;
ans,z:int64; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure suffix;
var i,j,p:longint;
begin
for i:= to n do
begin
y[i]:=ord(s[i]);
inc(sum[y[i]]);
end;
m:=;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[y[i]]]:=i;
dec(sum[y[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if y[sa[i]]<>y[sa[i-]] then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=;
while m<n do
begin
fillchar(sum,sizeof(sum),);
y:=rank;
p:=;
for i:=n-j+ to n do
begin
inc(p);
x[p]:=i;
end;
for i:= to n do
if sa[i]>j then
begin
inc(p);
x[p]:=sa[i]-j;
end; for i:= to n do
begin
rank[i]:=y[x[i]];
inc(sum[rank[i]]);
end;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[rank[i]]]:=x[i];
dec(sum[rank[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if (y[sa[i]]<>y[sa[i-]]) or (y[sa[i]+j]<>y[sa[i-]+j]) then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=j shl ;
end;
h[]:=;
p:=;
for i:= to n do
begin
if rank[i]= then continue;
j:=sa[rank[i]-];
while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p);
h[rank[i]]:=p;
if p> then dec(p);
end;
end; function calc(i,x,y:int64):int64;
begin
exit(*h[i]*(i-x)*(y-i));
end; begin
readln(s);
n:=length(s);
suffix;
z:=n;
ans:=(z+)*z div *(z-);
t:=;
for i:= to n do
begin
while (t>) and (h[q[t]]>=h[i]) do dec(t);
if t= then l[i]:=
else l[i]:=q[t];
inc(t);
q[t]:=i;
end;
t:=;
for i:=n downto do
begin
while (t>) and (h[q[t]]>h[i]) do dec(t); //注意右边界是第一个不大于的height,防止重复
if t= then r[i]:=n+
else r[i]:=q[t];
inc(t);
q[t]:=i;
end;
for i:= to n do
ans:=ans-calc(i,l[i],r[i]);
writeln(ans);
end.
bzoj3238的更多相关文章
- 【BZOJ3238】差异(后缀自动机)
[BZOJ3238]差异(后缀自动机) 题面 BZOJ 题解 前面的东西直接暴力算就行了 其实没必要算的正正好 为了方便的后面的计算 我们不考虑\(i,j\)的顺序问题 也就是先求出\(\sum_{i ...
- 【BZOJ3238】[AHOI2013]差异
[BZOJ3238][AHOI2013]差异 题面 给定字符串\(S\),令\(T_i\)表示以它从第\(i\)个字符开始的后缀.求 \[ \sum_{1\leq i<j\leq n}len(T ...
- 【bzoj3238】 Ahoi2013—差异
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 (题目链接) 题意 给出一个字符串,求${\sum_{1<=i<j<=n} ...
- 【BZOJ3238】[Ahoi2013]差异 后缀数组+单调栈
[BZOJ3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...
- [BZOJ3238][AHOI2013]差异(后缀数组)
求和式的前两项可以直接算,问题是对于每对i,j计算LCP. 一个比较显然的性质是,LCP(i,j)是h[rk[i]+1~rk[j]]中的最小值. 从h的每个元素角度考虑,就是对每个h计算有多少对i,j ...
- [BZOJ3238][Ahoi2013]差异解题报告|后缀数组
Description 先分析一下题目,我们显然可以直接算出sigma(len[Ti]+len[Tj])的值=(n-1)*n*(n+1)/2 接着就要去算这个字符串中所有后缀的两两最长公共前缀总和 首 ...
- 【bzoj3238】差异[AHOI2013](后缀数组+单调栈)
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3238 这道题从大概半年以前就开始啃了,不过当时因为一些细节没调出来,看了Sakits神犇 ...
- BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】
题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...
- bzoj3238 [Ahoi2013]差异 后缀数组+单调栈
[bzoj3238][Ahoi2013]差异 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Ou ...
- [bzoj3238][Ahoi2013]差异_后缀数组_单调栈
差异 bzoj-3238 Ahoi-2013 题目大意:求任意两个后缀之间的$LCP$的和. 注释:$1\le length \le 5\cdot 10^5$. 想法: 两个后缀之间的$LCP$和显然 ...
随机推荐
- win向linux传文件
使用pscp.exe即可. 下载pscp.exe(http://pan.baidu.com/s/1jG6zmx4) 复制到windows/system32目录下即可. 然后可在cmd命令行下使用psc ...
- ArcGIS Runtime SDK for WPF已不更新,后续将被ArcGIS Runtime SDK for .NET取代
ArcGIS Runtime SDK 10.2.5 for WPF is now available! by mbranscomb and Rex Hansen on January 27, 2015 ...
- Quartz2.2.1操作手册
一.初识quartz JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1") ...
- IOS 学习日志 2015-3-13
前面几天在看C ,但是没有做笔记,现在在看Objective--C ,开始做笔记,希望每一天都有成长吧 Objective--C 关键字 1 @import 导入 注意<>||" ...
- 专题二、ArrayList序列化技术细节详解
一.绪论 所谓的JAVA序列化与反序列化,序列化就是将JAVA 对象以一种的形式保持,比如存放到硬盘,或是用于传输.反序列化是序列化的一个逆过程. JAVA规定被序列化的对象必须实现java.io.S ...
- nginx 自定义代理返回 404
在nginx的http段,加上一面的配置 proxy_intercept_errors on;//自定义代理返回的404错误提示
- jquery 实现复选框单选
$(function() { $(':checkbox[name=复选框name值]').each(function() { $(this).click(function() { if ($(t ...
- jsonp跨域访问详解
jsonp是"用来跨域的" 同源策略 首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 1.随便建两个网 ...
- (转载)delphi 把图片存入数据库
delphi 把图片存入数据库 procedure TForm1.Button1Click(Sender: TObject); // 插入图片过程var Stream:TMemoryStream;be ...
- android中listview的item滑动删除效果(已解决listview点击问题)
领导看到iphone上tableview有个滑动删除的效果,要求在android上也实现,搜了下资料,实现起来比较简单,可弄到后面,居然不能点击了,把一篇文章中的代码修改了一下,捣鼓了一番,搞定,下面 ...