P4000 [Ahoi2013]差异
问题描述
输入格式
一行,一个字符串S
输出格式
一行,一个整数,表示所求值
样例输入
cacao
样例输出
54
提示
2<=N<=500000,S由小写英文字母组成
还是先说优美的自动机做法,将字符串反过来建立后缀自动机,那么后缀的前缀变成前缀的后缀,那么变成在后缀自动机parent树上求LCA
考虑到所有的LCP要求和,那么考虑每一个节点会多少次被当做LCA,显然如果统计出每颗子树Right集合的大小,即子树表示了多少个前缀,那么两两子树的前缀数相乘求和就是当前点被当做LCA的次数。因为不同子树中的点的LCA一定是当前节点。
然后还要考虑选择了子树中的一个点和当前点的情况,此时需要注意到统计Right集合时,复制出来的点并不代表一次新的出现位置,因此只有当当前点不是复制的点时,才加上每个子树的前缀数。
代码:
1 |
|
然后是略微麻烦的后缀数组做法。
优秀的思路是考虑每一个Height有多少次被作为LCP加入答案,那么显然需要找到左右第一个小于他的位置。用单调队列/栈即可。但是需要注意由于Height相同而产生的重复计算。
一个更粗暴的想法是直接用线段树维护当前的已经求出的LCP值,每次讨论一个新的Height时,把大于他的LCP值变成当前的Height,然后新加入一个Height,然后对整颗线段树求和累加到答案上即可。
代码:
1 |
|