码迷,mamicode.com
首页 > 编程语言 > 详细

[知识点]后缀数组

时间:2015-08-20 01:11:26      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:

// 本文部分内容参照刘汝佳《算法竞赛入门经典训练指南》,特此说明。

1、前言

  趁着这几天上午,把后缀数组大致看完了。这个东西本身的概念可能没太大理解问题,但是它所延伸出来的知识很复杂,很多,还有它的两个兄弟——后缀树,后缀自动机,编起来都不是盖的。

 

2、概念

  前面曾经提到过Aho-Corasick自动机(http://www.cnblogs.com/jinkun113/p/4682853.html),讲得有点简略。。。它用以解决多模板匹配问题。但是前提是事先知道所有的模板,在实际应用中,我们无法事先知道查询内容的,比如在搜索引擎中,你的查询是不可能直接预处理出来的。这个时候就需要预处理文本串而非每次的查询内容。后缀数组,说的简单一点,就是将一个字符串的所有后缀储存起来的数组,接下来分析它的作用。

 

3、构建

首先假定一个字符串BANANA,在后面添加一个非字母字符“$”,代表一个没出现过的标识字符,然后把它的所有后缀——BANANA$,ANANA$,NANA$,ANA$,NA$,A$插入到一棵Trie中。由于标识字符的存在,字符串每一个后缀都与一个叶节点一一对应。如图所示:

[Picture invalid]

在实际应用中,会把后缀Trie中没有分支的链合并在一起,得到所谓的后缀树,但是由于后缀树的构造算法复杂难懂,且容易写错,所以在竞赛中很少使用,所以暂时不去研究了。相比之下,后缀数组是必备武器,时间效率高,代码简单,而且不易写错。

在绘制后缀Trie的时候,我们将字典序小的字母排在左边。由于叶节点和后缀一一对应,我们现在在每一个叶节点上标上该后缀的首字母在原字符串中的位置,如图:

[Picture invalid]

将所有下标连在一起,构建出来的,就是所谓的后缀数组了。BANANA的后缀数组为sa[]={5,3,1,0,4,2}。而根据所建后缀Trie易得,这是根据每一个后缀的字典序进行的排序。这样的话,我们就可以直接通过一次快速排序O(n log n)得到了。但是,在比较任意两个后缀时,又需要O(n),故这是O(n^2 log n),根本扛不住。

 

4、倍增

下面介绍Manber和Myers发明的倍增算法,时间复杂度O(n log n)(不采用基数排序的话就是O(n log^2 n))。

首先对于所有单个字符排序(也可以理解成对于每一个后缀的第1个字符排序,这样后面的步骤更易衔接),如图:

[Picture invalid]

对于每个字母,

[知识点]后缀数组

标签:

原文地址:http://www.cnblogs.com/jinkun113/p/4743694.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!