后缀数组的简单自用定理和技巧自用
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[]\)数组。
2.对于后缀数组快速求两个子串的\(lcp\)
前置,两个子串的\(lcp\)为它们之前所有\(H[]\)的最小值。
所以
先切好所有\(H[]\)
放到\(st\)表里面一锅煮。
然后\(O(nlogn)\)慢炖。
最后就可以愉快的\(O(1)\)品尝了!
3.对于后缀数组求相同回文子串
用回文自动机多好
大概是利用manacher处理出本质不同的回文串
然后记录当前位置,就可以利用\(rmq+H[]\)查到有多少个\(H[]\)长度与这个回文子串相同的其它回文子串了。
4.对于后缀数组求本质不同的子串
这大概是一个公式qwq
\(n*(n-1)/2-\sum_{i=1}^{n}H[i]\)
这大概就是先把所有的相同子串默认都是本质不同的
然后因为对于\(H[i]\),有一段子串是相同的,这意味着我们多算了一遍,把它减去就可以了。
5.对于后缀数组求环的sa排序
断环成链倍增咯。
某些情况下不能直接加上去,可以在后面加上一个没有出现过的字符。
这种方法可以用来处理掉两个子串求相同子串等问题吧。
6.关于一些后缀数组的练习题?
[TJOI2017]DNA
[NOI2015]品酒大会
[NOI2016]优秀的拆分
[USACO07DEC]最佳牛线,黄金Best Cow Line, Gold
[HAOI2016]找相同字符
[SCOI2012]喵星球上的点名