在这之前我对串的全部认识就是kmp一家,应该说这次学习后缀数组总算是让我对串这种东西有了个基本的认识吧。
之前有听说过后缀树和后缀数组,感觉上跟线段树树状数组的关系差不多,不过貌似后缀数组的应用范围也很广吧
好了,进入正题
后缀数组,顾名思义,就是由一些后缀组成的数组,这些后缀就是原串中以i开头的后缀
但单是这么个数组没用,我们要使他有一些性质才有用,怎么做呢?排序?
没错,就是排序,可以感性地想想,如果对这些后缀按字典序排序,是不是排完序后相邻的两个后缀会是最“相似”的?
具体的性质稍后讨论,先看看怎么对其排序
如果裸的排序比较的话,每次比较的复杂度是O(n)的,那么总的复杂度达到了O(n^2logn),相当差,需要考虑更强大的方法
这里介绍一下针对这个问题的倍增算法,它的复杂度可以做到O(nlogn),基本上可以搞定大部分题目了
这个算法大概就是利用字典序的特殊比较方法和倍增的思想,减少了比较的次数,并充分利用上了之前的比较结果,所以优化了原算法
先讲两个个很显然的性质吧:
1.若两个后缀的前几位比较已经出结果了,那么就不用比下去了
2.对于两个长度为2k的串,若知道每对长为k的串的大小关系,就可以O(1)的判断出这两个串的大小关系
利用简单的性质构造出神奇的算法,或许这就是oi的诱人之处吧
具体算法如下(蒯自集训队论文2009罗穗骞)
用倍增的方法对每个字符开始的长度为2k 的子字
符串进行排序,求出排名,即rank 值。k 从0 开始,每次加1,当2k 大于n 以
后,每个字符开始的长度为2^k 的子字符串便相当于所有的后缀。并且这些子字
符串都一定已经比较出大小,即rank 值中没有相同的值,那么此时的rank 值就
是最后的结果。每一次排序都利用上次长度为2^(k-1) 的字符串的rank 值,那么长
度为2k 的字符串就可以用两个长度为2^(k-1) 的字符串的排名作为关键字表示,然
后进行基数排序,便得出了长度为2^k 的字符串的rank 值
如果排序用基数排序的话,总的复杂度就是O(nlogn)了
后缀数组还有一个叫DC3的算法,复杂度是O(n),但那个算法中过多排序让常数不太漂亮,而且编程复杂度大些,所以不做介绍了,有兴趣可以去看看上面提到的那篇论文
后缀数组中还有一个很重要的东西:height[]它表示后缀数组中rank[i]和rank[i-1]的lcs的长度
有了下面这个结论height数组就很容易求了
height[rank[i]]>=height[rank[i]-1]-1
严格证明网上有,我是这样理解的,后缀数组中相邻的两个是“最相似”的,第i个和第i-1个的lcs都是k了,那i+1和i的lcs至少也是k-1嘛,(好像有点萎的解释,其实这里我还没理解透)不管怎么样,这样求就可以做到O(n)了
下面是我的模板
我们使用后缀数组的时候要特别想清楚该用SA[I]还是RANK[I]还是就是I,不然会错的很冤枉的
还有有个注意的地方倍增的时候,只要每个元素的标号都不同就可以结束了,即while o<>n do 而不必写成 while l<n do
这两个写法常数差距很大(实测5~10倍的区别)
下面简单介绍几个简单应用:
0.求一个串的最长可重叠子串:直接扫一遍height数组即可
1.求两个串的最长公共子串(PKU 2774):
把两个串连起来,中间搞个不可能出现的字符,最后扫一遍height数组取个max即可,只有一个要求,SA[RANK[I]]和SA[RANK[I]-1]必须属于两个不同的串
2.求一个串的最长不重叠字串(PKU1743的核心算法):
(蒯自zfy0701博客)
现在我们假设-最长,不重叠,重复-子串的长度为len,那么在一个height数组中有一些hgt[i]会小于len,在这个i左右的两个子串,他们LCP是不可能大于或等于len的,这样,就可以吧height数组看做很多LCP >= len的段,我们在每一段中进行扫描,记录这一段中最大和最小的子串串索引(sa[x])(注意,算i的时候要同时取sa[i-1]和sa[i]来更新),如果两者之和小于len,说明重叠了,否则就找到一个可行解。
易证:如果该串存在len1的不重叠子串,且len1 > len2,则该串也存在长度len2的不重叠子串,解有连续性,所以我们在上面这个过程外我们可以二分枚举解。
对了,二分查找之前之前可先调用查找len = 4是否成立,不成立就直接return了。
这道题的关键点就是:判断解的时候对height数组进行分段处理,这个分段的思想与其说重要,还不说就是height数组的基本性质。
3.求两个字符串不小于k的公共子串的个数(PKU3415):
此题较难,可直接看http://hi.baidu.com/zfy0701/blog/item/f2278a0928991dca3bc763a0.html写的很清楚
貌似字符串还有一些神级算法什么什么自动机来的,暂时就不搞了吧
下一个目标,计算几何