后缀数组自用

后缀数组的简单自用定理和技巧自用

1.对于H[]数组的定义

前置:
\(lcp(x,y)\)表示字符串\(x\)\(y\)最长公共前缀。
\(height[i]\)\(lcp(sa[i],sa[i-1])\)
\(H[i]\)\(height[rak[i]]\),表示当前位置与前一个排名的最长公共前缀。
那么显然\(H[i]>=H[i-1]-1\)
因为\(H[i-1]\)可以保证的是\(i-1\)后面也许会有一个后缀是\(i-1\)的前缀。
要不就是0;
可以想到既然\(i-1\)\(i\)只相差一位,那么是不是那个属于\(i-1\)的前缀的在后面出现的后缀,再推后一位就是第i位的前缀了呢?

Ps:\(rak[i]\)为当前i位置后缀的排名。

作用:可以\(O(n)\)快速求出\(H[]\)数组。

例题:# [USACO06DEC]牛奶模式

2.对于后缀数组快速求两个子串的\(lcp\)

前置,两个子串的\(lcp\)为它们之前所有\(H[]\)的最小值。
所以
先切好所有\(H[]\)
放到\(st\)表里面一锅煮。
然后\(O(nlogn)\)慢炖。
最后就可以愉快的\(O(1)\)品尝了!

3.对于后缀数组求相同回文子串

用回文自动机多好

大概是利用manacher处理出本质不同的回文串
然后记录当前位置,就可以利用\(rmq+H[]\)查到有多少个\(H[]\)长度与这个回文子串相同的其它回文子串了。

[APIO2014]回文串

4.对于后缀数组求本质不同的子串

这大概是一个公式qwq

\(n*(n-1)/2-\sum_{i=1}^{n}H[i]\)

这大概就是先把所有的相同子串默认都是本质不同的
然后因为对于\(H[i]\),有一段子串是相同的,这意味着我们多算了一遍,把它减去就可以了。

不同子串个数

5.对于后缀数组求环的sa排序

断环成链倍增咯。
某些情况下不能直接加上去,可以在后面加上一个没有出现过的字符。
这种方法可以用来处理掉两个子串求相同子串等问题吧。

[JSOI2007]字符加密

6.关于一些后缀数组的练习题?

[TJOI2017]DNA
[NOI2015]品酒大会
[NOI2016]优秀的拆分
[USACO07DEC]最佳牛线,黄金Best Cow Line, Gold
[HAOI2016]找相同字符
[SCOI2012]喵星球上的点名

posted @ 2019-03-06 21:45  Epiphyllum_thief  阅读(178)  评论(1编辑  收藏  举报