题目分析:

求出height以后很明显跨越最小height的一定贡献是最小height,所以对于区间找出最小height再将区间对半分。

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ;
const int N = ; int n;
char str[maxn]; int sa[maxn],rk[maxn],X[maxn],Y[maxn];
int height[maxn],h[maxn],RMQ[maxn][],pos[maxn][]; int chk(int x,int k){
return rk[sa[x]]==rk[sa[x-]]&&rk[sa[x]+(<<k)]==rk[sa[x-]+(<<k)];
} void getsa(){
for(int i=;i<n;i++) X[str[i]]++;
for(int i=;i<=N;i++) X[i] += X[i-];
for(int i=n-;i>=;i--) sa[X[str[i]]--] = i;
for(int i = , num = ;i <= n;i++)
rk[sa[i]] = (str[sa[i]] == str[sa[i-]]?num:++num);
rk[sa[]] = ;
for(int k=;(<<k-)<=n;k++){
for(int i=;i<=N;i++) X[i] = ;
for(int i=n-(<<k-);i<n;i++) Y[i-n+(<<k-)+]=i;
for(int i=,j=(<<k-)+;i<=n;i++)
if(sa[i]>=(<<k-))Y[j++]=sa[i]-(<<k-);
for(int i=;i<n;i++) X[rk[i]]++;
for(int i=;i<=N;i++) X[i]+=X[i-];
for(int i=n;i>=;i--) sa[X[rk[Y[i]]]--] = Y[i];
int num = ; Y[sa[]] = ;
for(int i=;i<=n;i++) Y[sa[i]] = (chk(i,k-)?num:++num);
for(int i=;i<n;i++) rk[i] = Y[i];
if(num == n) break;
}
}
void getheight(){
for(int i=;i<n;i++){
if(i) h[i] = max(,h[i-]-); else h[i] = ;
if(rk[i] == ) continue;
int comp = sa[rk[i]-];
while(str[comp+h[i]] == str[i+h[i]])h[i]++;
}
for(int i=;i<n;i++) height[rk[i]] = h[i];
for(int i=;i<=n;i++) RMQ[i][] = height[i],pos[i][] = i;
for(int k=;(<<k)<=n;k++){
for(int i=;i<=n;i++){
if(i+(<<k-)>n) RMQ[i][k]=RMQ[i][k-],pos[i][k]=pos[i][k-];
else {
if(RMQ[i][k-]<RMQ[i+(<<k-)][k-]) pos[i][k] = pos[i][k-];
else pos[i][k] = pos[i+(<<k-)][k-];
RMQ[i][k] = min(RMQ[i][k-],RMQ[i+(<<k-)][k-]);
}
}
}
}
int getLCP(int L,int R){
if(L > R) swap(L,R);
if(L == R) return n-sa[L];
L++;
int k = ; while((<<k+)<=R-L+)k++;
if(RMQ[L][k]<RMQ[R-(<<k)+][k]) return pos[L][k];
else return pos[R-(<<k)+][k];
} long long ans = ; void divide(int l,int r){
if(l == r) return;
int ps = getLCP(l,r);
ans -= 2ll*(ps-l)*(r-ps+)*height[ps];
divide(l,ps-); divide(ps,r);
} void work(){
n = strlen(str);
getsa();
getheight();
for(int i=;i<=n;i++) ans += 1ll*i*i-i;
for(int i=;i<=n;i++) ans += 1ll*i*(n-i);
divide(,n);
printf("%lld\n",ans);
} int main(){
scanf("%s",str);
work();
return ;
}

AHOI2013 差异 【后缀数组】的更多相关文章

  1. bzoj 3238: [Ahoi2013]差异 -- 后缀数组

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个 ...

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

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

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

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

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

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

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

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

  6. [BZOJ3238][AHOI2013]差异(后缀数组)

    求和式的前两项可以直接算,问题是对于每对i,j计算LCP. 一个比较显然的性质是,LCP(i,j)是h[rk[i]+1~rk[j]]中的最小值. 从h的每个元素角度考虑,就是对每个h计算有多少对i,j ...

  7. 【bzoj3238】差异[AHOI2013](后缀数组+单调栈)

    题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3238 这道题从大概半年以前就开始啃了,不过当时因为一些细节没调出来,看了Sakits神犇 ...

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

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

  9. BZOJ 3238: [Ahoi2013]差异 [后缀自动机]

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

  10. [Ahoi2013]差异(后缀自动机)

    /* 前面的那一坨是可以O1计算的 后面那个显然后缀数组单调栈比较好写??? 两个后缀的lcp长度相当于他们在后缀树上的lca的深度 那么我们就能够反向用后缀自动机构造出后缀树然后统计每个点作为lca ...

随机推荐

  1. eletron打包

    https://www.cnblogs.com/BigJ/p/electron.html https://www.cnblogs.com/kakayang/p/9559777.html

  2. 蛙蛙推荐: TensorFlow Hello World 之平面拟合

    tensorflow 已经发布了 2.0 alpha 版本,所以是时候学一波 tf 了.官方教程有个平面拟合的类似Hello World的例子,但没什么解释,新手理解起来比较困难. 所以本文对这个案例 ...

  3. JSF生存指南P1

    这是OO的第三次博客作业,也是JSFO(面向JSF编程)的第一次博客作业.暗示了我们面向对象课程已经再向JSF的编写过渡. 不知不觉OO的作业已经写完3/4,那些熬夜赶作业的日子仍然历历在目,仿佛是昨 ...

  4. Python遇到问题总结

    1.list的集合 循环删除一个list数据时,会遇到一丢丢问题,详情看Python的list循环遍历中,删除数据的正确方法 但是,里面说的要反转一下list集合,可以用a[::-1]这种方法. &g ...

  5. Python学习第十二篇——切片的使用

    Python中使用函数切片可以创建副本,保留原本.现在给出如下代码 magicians_list = ['mole','jack','lucy'] new_lists = [] def make_gr ...

  6. 02-安装linux系统

    安装linux系统 需要准备的软件: 1.VMware-workstation-full-14.1.1.28517.exe 2.CentOS-6.5-x86_64-bin-DVD1.iso镜像文件 第 ...

  7. html总结:float实现span和input输入框同行

    例: <input type="text" name="ytdwname" value="<%=user.getYtdwname() %& ...

  8. redis4.X

    tar -zxvf ****cd /redismakecd /srcmake install vi redis.confdaemonize yes mkdir /usr/local/redis/bin ...

  9. centOS 7下无法启动网络(service network start)错误解决办法

    今天在centOS 7下更改完静态ip后发现network服务重启不了,翻遍了网络,尝试了各种方法,终于解决了. 现把各种解决方法归纳整理,希望能让后面的同学少走点歪路... 首先看问题:执行serv ...

  10. DAY06、元组、字典、集合

    一.元组 1.定义:参数为for可以循环的对象 t1 = (1, 2)     t2 = tuple((1, 2))     t3 = (1, )        #定义一个只有一个值的元组 2.常用操 ...