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

接下来问题就是如何把LCP减去。我们先用后缀数组把height求出来,当有一段区间l~r,height[i]为height[l]~height[r]中的最小值,那么随便取rk[l]~rk[r]中的两个后缀,他们的LCP则都是height[i],这个很好理解吧。那么l~r这个区间里有(l-i+1)*(r-i+1)对后缀,所以我们最后的答案就要减去2*height[i]*(l-i+1)*(r-i+1)【1≤i≤n】。

然后就是如何求出每一个i的l~r了,暴力枚举+RMQ显然不行,那我们就用一个单调栈,栈里存着i前面height值比height[i]小的height值的编号,记为j,如果height[j]比height[i]大那么就弹出,那么这段区间的左端点则为栈顶的j+1,右端点同理。这样我们就可以求出每个height的l和r了。

奇丑无比的代码如下:

var
s:ansistring;
i:longint;
n,m,l,r,ans,top:int64;
rk,trk,sa,tsa,sum,h,ll,rr,st:array[..]of int64; procedure suffix;
var
i,j,p:longint;
begin
for i:= to n do begin trk[i]:=ord(s[i]);inc(sum[trk[i]]);end;
for i:= to do inc(sum[i],sum[i-]);
for i:=n downto do begin sa[sum[trk[i]]]:=i;dec(sum[trk[i]]);end;
rk[sa[]]:=;p:=;
for i:= to n do begin if trk[sa[i]]<>trk[sa[i-]] then inc(p);rk[sa[i]]:=p;end;
m:=p;j:=;
while m<n do
begin
move(rk,trk,sizeof(rk));fillchar(sum,sizeof(sum),);p:=;
for i:=n-j+ to n do begin inc(p);tsa[p]:=i;end;
for i:= to n do if sa[i]>j then begin inc(p);tsa[p]:=sa[i]-j;end;
for i:= to n do begin rk[i]:=trk[tsa[i]];inc(sum[rk[i]]);end;
for i:= to n do inc(sum[i],sum[i-]);
for i:=n downto do begin sa[sum[rk[i]]]:=tsa[i];dec(sum[rk[i]]);end;
rk[sa[]]:=;p:=;
for i:= to n do
begin
if (trk[sa[i]]<>trk[sa[i-]])or(trk[sa[i]+j]<>trk[sa[i-]+j])then inc(p);
rk[sa[i]]:=p;
end;
m:=p;j:=j*;
end;
h[]:=;p:=;
for i:= to n do
begin
if rk[i]= then continue;
j:=sa[rk[i]-];
while s[i+p]=s[j+p] do inc(p);
h[rk[i]]:=p;
if p> then dec(p);
end;
end; begin
readln(s);
n:=length(s);
s:=s+' ';
suffix;
ans:=n*(n-)*(n+)div ;
h[]:=-maxlongint;
for i:= to n do
begin
while h[i]<=h[st[top]] do dec(top);
if st[top]= then ll[i]:=
else ll[i]:=st[top]+;
inc(top);
st[top]:=i;
end;
h[n+]:=-maxlongint;top:=;st[]:=n+;
for i:=n downto do
begin
while h[i]<h[st[top]] do dec(top);
if st[top]=n+ then rr[i]:=n
else rr[i]:=st[top]-;
inc(top);
st[top]:=i;
end;
for i:= to n do
ans:=ans-*(i-ll[i]+)*(rr[i]-i+)*h[i];
writeln(ans);
end.

[bzoj3238]差异(后缀数组+单调栈)的更多相关文章

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

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

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

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

  3. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

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

  4. [AHOI2013] 差异 - 后缀数组,单调栈

    [AHOI2013] 差异 Description 求 \(\sum {len(T_i) + len(T_j) - 2 lcp(T_i,T_j)}\) 的值 其中 \(T_i (i = 1,2,... ...

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

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

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

    题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...

  7. BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈

    BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...

  8. 【BZOJ3879】SvT 后缀数组+单调栈

    [BZOJ3879]SvT Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干 ...

  9. BZOJ_3879_SvT_后缀数组+单调栈

    BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...

  10. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

随机推荐

  1. nexus实现从windows迁移至Linux平台

    说明: 由于老环境是在本地windows 2008 R2里面搭建的nexus,前面搭建了jenkins,需要将maven私库迁移至云服务器的CentOS 7系统下,之前没做过nexus的迁移,在网上看 ...

  2. JavaScript里的循环方法之forEach,for-in,for-of

    JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标 ...

  3. 获取文件夹下某个类型的文件名---基于python

    方法1:import osclass flist_name(): def __init__(self,path): self.flist_name=os.listdir(path) def pcap_ ...

  4. Alpha发布——视频博客

    1.视频链接 视频上传至优酷自频道,地址链接:https://v.youku.com/v_show/id_XMzg5MzQ4MzM2MA==.html?spm=a2h0k.11417342.sores ...

  5. 2017软工第十周个人PSP

    11.17--11.23本周例行报告 1.PSP(personal software process )个人软件过程. C(类别) C(内容) ST(开始时间) ET(结束时间) INT(间隔时间) ...

  6. UVALive - 6916 Punching Robot Lucas+dp

    题目链接: http://acm.hust.edu.cn/vjudge/problem/96344 Punching Robot Time Limit: 1000MS64bit IO Format: ...

  7. C#高级编程 (第六版) 学习 第七章:委托和事件

    第七章 委托和事件 回调(callback)函数是Windows编程的一个重要方面,实际上是方法调用的指针,也称为函数指针. .Net以委托的形式实现了函数指针的概念,.Net的委托是类型安全的. 委 ...

  8. C++ Primer Plus学习:第三章

    C++入门第三章:处理数据 面向对象编程(OOP)的本质是设计并扩展自己的数据类型. 内置的C++数据类型分为基本类型和复合类型. 基本类型分为整数和浮点数. 复合类型分为数组.字符串.指针和结构. ...

  9. Swift-闭包使用及解决循环引用问题

    Swift中闭包使用参考OC中block使用,基本一致 // 闭包类型 首先写(参数列表)->(返回值类型) func loadData(callBack : (jsonData:String) ...

  10. XHTML语法规范

    <head> <meta charset="utf-8" /> <title>xhtml语法规范</title> </head ...