搞了这么多后缀数组,写个总结
其实罗穗赛的论文里已经都总结得很清楚了。我这里对一些代码的具体实现细节和一些要注意的地方做一些说明。
后缀数组很重要的三个数组就是:rank[],sa[]和height[]了
其中rank[i]表示i这个后缀的排名,sa[i]表示排在第i位的后缀的首字母位置,height[i]表示排名第i的后缀和排名i-1的后缀的lcp(最长公共前缀)
其中最重要的就是height数组了,我们所有的计算几乎都是要用到height数组,而sa和rank数组则是用于找到我们需要的height
后缀数组的题目大致可以分为以下三类:
1、对单个字符串的处理,诸如求最长公共子串,求不同的子串数,求出现k次不重叠的子串等等
其中最长公共子串直接求height数组的最大值就好了,因为sa[i]和sa[j]的lcp为min(height[i+1],height[i+2]....height[j]),注意这里是从height[i+1]开始,因为height[i+1]是表示i+1和i的lcp,对于height数组这样的表示,很容易在一些地方出错
而不同的子串数则是所有的子串数减去各height值,我们可以这样子来理解,对于sa[i]这个后缀,我们有height[i]个子串是在sa[i-1]中前面已经计算过了,所以减去就好
还有一道楼教主男人8题之一的,是求一个重复出现两次以上不重叠的子串,这道题的处理很巧妙,同时也要多注意转化后的数组和原数组之间的关系,具体做法:http://blog.csdn.net/lj94093/article/details/45056891
2、对两个字符串的处理,也是求最长重复子串之类的
对于两个及以上的字符串的处理办法,都是把后面的字符串接在第一个字符串后面,中间加分隔符隔开,由于一般这样的题都不需要计算排名,所以加一个在所有字符串中都没有出现的数就可以了
通过height[i]值分组这样的思想也是很常见的,主要用于求长度大于k的子串
这里特别说一下:http://blog.csdn.net/lj94093/article/details/45079269 这道题是求两字符串的公共子串直接枚举那肯定会超时,我们这里用到了一个单调栈,每次加进来一个数的时候,如果比栈顶的数小,那么栈顶出栈,更新相应的权值和对应的公共子串数,直到栈为空或该数比栈顶大
还有一道是求A串里没有在B串中出现过的不同子串数,用总数减去和B重复的就好,然后还要注意A串里自己去重
3、多字符串的处理,这样的题和两个字符串的处理也大同小异,就不说了
原文地址:http://blog.csdn.net/lj94093/article/details/45308229