因为涉及到对模板的理解,所以就着代码看会好一些。

让那些坚决不颓代码的人受委屈了。

我是对着wzz的板子默写的,可能不完全一样啊。

还有代码注释里都是我个人的理解,不保证正确,但欢迎指正。

可以有选择的浏览,单调栈的那个非模板部分可以不看,自己想。

因为写的稍微有点详细所以在网页上极丑,粘到自己gedit上看吧。

 #include<cstdio>
#include<algorithm>
#define int long long
char s[];
int x[],y[],sa[],rk[],l=,c[],m=,h[];
int sta[],sta2[],top,ans,tr[],tl[];
main(){
scanf("%s",s);
while(s[l]) l++;//统计长度。在末尾加上了一个空字符
for(int i=;i<=l;++i) c[s[i]?x[i]=s[i]-'a'+:]++;//统计各字符出现次数,顺便把字符串s转化为数串x
for(int i=;i<=m;++i) c[i]+=c[i-];//累加得到出现次数的前缀和,相当与划分出了多个区间
for(int i=l;~i;--i) sa[--c[x[i]]]=i;//初步确定每个范围里有哪些串,但内部排名未知
for(int len=,p=;len<=l+;len<<=,p=){//枚举前后两截(二元组)的长度,倍增求解每个串在长度为len<<1的所有串中的排名
for(int i=l;i>=l-len+;--i) y[p++]=i;//没有后半截的直接记录,y数组存的是前半截(也就是整个串)的起始位置,y有序因为空字符的字典序最小
for(int i=;i<=l;++i) if(sa[i]>=len) y[p++]=sa[i]-len;//有后半截的,那就记录下它对应的左半截,注意y已经是后半截有序的
for(int i=;i<=m;++i) c[i]=;//清空字符出现次数
for(int i=;i<=l;++i) c[x[i]]++;//重新累加每个长度为len的字符串的出现次数
for(int i=;i<=m;++i) c[i]+=c[i-];//还是前缀和,完全和循环外面的一样,划分出大致区间
for(int i=l;~i;--i) sa[--c[x[y[i]]]]=y[i];//对于每个串的前半截讨论其排名,前半截有序了,排名相同的按后半截也拍好序了(因为y已经有序)
p=;std::swap(x,y); x[sa[]]=;//清空p,xy数组滚动交换,确定排名第0的串是一个空串
for(int i=;i<=l;++i) x[sa[i]]=y[sa[i]]==y[sa[i-]]&&y[sa[i]+len]==y[sa[i-]+len]?p:++p;//类似离散化,求出已经区分开的串的种数,并更新字符串和字典序排名
if(p==l)break;else m=p;//如果已经全部区分开了,可以跳出循环,否则更新串种数然后继续区分
}
for(int i=;i<=l;++i) rk[sa[i]]=i;//求出sa的逆数组,表示排名为i的串的开始位置
for(int i=,k=;i<=l;h[rk[i++]]=k,k=k?k-:) while(s[i+k]==s[sa[rk[i]-]+k]) k++;//求height,s[i+k]可以写作s[sa[rk[i]]+k]更好理解,注意h[1]是无用的因为sa[1]是空串
//性质:排名为i,j(i<j)的后缀的lcp为min{height[k]|i+1≤k≤j}
//转化:已知一段序列,求所有字串的最小值的和--两次单调栈(内部元素是底小顶大),求解左右多大的区间能以这个值为最小值
sta[]=-;h[l+]=-;h[]=-;//与后面的弹栈元素等有关,-3直接入栈压底防止弹栈弹多了,其余两个都是用来强制所有正常元素弹栈
for(int i=;i<=l+;++i){//注意这里到了l+1,也就是用-2强制弹干净栈中所有的元素(除了压底的-3)
while(sta[top]>=h[i])tr[sta2[top--]]=i-;//当一个元素被弹出,一定是遇到了右侧第一个小于等于它的元素,那么自然以此为右端点的区间内最小值为这个元素
sta[++top]=h[i];sta2[top]=i;//入栈,记录位置
}
for(int i=l;i;--i){//倒着单调栈,求出它能控制的左端点,用h[1]=-1强制弹栈
while(sta[top]>h[i])tl[sta2[top--]]=i+;//注意这里没有等号,否则当有相等的height值时会重复计算(对于测试点abbab好像就不行)
sta[++top]=h[i];sta2[top]=i;
}
for(int i=;i<=l;++i)ans+=h[i]*(tr[i]-i+)*(i-tl[i]+);//区间右端点在i~tr[i]内任选,左端点在tl[i]~i内任选,这时区间最小值都是h[i],记录方案数乘权值
printf("%lld\n",((l-)*l*(l+)>>)-(ans<<));
}

差异:后缀数组(wzz模板理解),单调栈的更多相关文章

  1. 后缀数组Da模板+注释 以及 dc3模板

    后缀数组Da模板: 1 /* 2 后缀数组倍增法Da板子 3 */ 4 #include <cstdlib> 5 #include <cstring> 6 #include & ...

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

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

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

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

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

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

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

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

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

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

  7. UOJ35 后缀数组(模板)

    #35. 后缀排序 这是一道模板题. 读入一个长度为 nn 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置.位置编号为 1 ...

  8. P5788 【模板】单调栈

    ---------------- 链接:Miku ---------------- 单调栈模板终于不是一堆蓝题了!!!!!!!!!!!! 单调栈,就是单调的栈,栈内元素都是单调的. 题目要求我们求出来 ...

  9. 题解【洛谷P5788】【模板】单调栈

    题面 单调栈模板题. 单调栈与单调队列一样,都是维护了一段区间内的顺序. 然后--这个题用一个栈维护一下贪心就没了. 具体参考这一篇题解 #include <bits/stdc++.h> ...

随机推荐

  1. css3:bacground-size

    个人博客: https://chenjiahao.xyz CSS3之背景尺寸Background-size是CSS3中新加的一个有关背景的属性,这个属性是改变背景尺寸的通过各种不同是属性值改变背景尺寸 ...

  2. 检测 IP的正则表达式

    ... /*ip正则表达式*/ /^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})| ...

  3. git分支的创建、删除、切换、合并

    需求背景 开发新功能和修改bug一般放在新建分支,如果觉得可行,可以合并到master分支上. 方式 1.查看分支 git branch (查看本地分支及当前所属分支) git branch -a ( ...

  4. Zookeeper未授权访问测试

    前言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...

  5. Vue3都使用Proxy了,你更应该了解Proxy

    vue3.0的pre-alpha版代码已经开源了,就像作者之前放出的消息一样,其数据响应这一部分已经由ES6的Proxy来代替Object.defineProperty实现,感兴趣的同学可以看其实现源 ...

  6. Fiddler的基本使用

    目录 清空历史请求 请求所消耗的时间 发送的数据在 设置fiddler过滤请求 模拟弱网环境 Ctrl+R 拦截数据,拦截数据又称"打断点" fiddler开启的时候就是默认开始抓 ...

  7. [USACO17FEB]Why Did the Cow Cross the Road III S

    题目描述 Why did the cow cross the road? Well, one reason is that Farmer John's farm simply has a lot of ...

  8. [POI2015]PIE

    题目描述 一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色.你有一个a*b的印章,有些格子是凸起(会沾上墨水)的.你需要判断能否用这个印章印出纸上的图案.印的过程中需要满足以下要求:( ...

  9. 【Cocos2d-x】学习笔记目录

    从2019年7月开始学习游戏引擎Cocos2dx,版本3.17. 学习笔记尽量以白话的形式表达自己对源码的理解,而不是大篇幅复制粘贴源码. 本人水平有限,欢迎批评指正! Cocos2d-x 学习笔记 ...

  10. Service Mesh 初体验

    前言 计算机软件技术发展到现在,软件架构的演进无不朝着让开发者能够更加轻松快捷地构建大型复杂应用的方向发展.容器技术最初是为了解决运行环境的不一致问题而产生的,随着不断地发展,围绕容器技术衍生出来越来 ...