[IR] Suffix Trees and Suffix Arrays
前缀树
匹配前缀字符串是不言自明的道理。
1. 字符串的快速检索
2. 最长公共前缀(LCP)
等等
树的压缩
后缀树
Let s=abab, a suffix tree of s is a compressed trie of all suffixes of s=abab$
后缀树的构建:由长到短,逐渐增加。完毕后进行“树的压缩”。
右图绿色leaf node表示对应子串的起始位置。【ith】
Construct Suffix Tree
O(n2) --> O(n), how?
在 1995 年,Esko Ukkonen 发表了论文《On-line construction of suffix trees》,描述了在线性时间内构建后缀树的方法。下面尝试描述 Ukkonen 算法 的基本实现原理,从简单的字符串开始描述,然后扩展到更复杂的情形。
Ref: http://www.cnblogs.com/gaochundong/p/suffix_tree.html
Ref: https://stackoverflow.com/questions/9452701/ukkonens-suffix-tree-algorithm-in-plain-english
鉴于Suffix Array要优于Suffix Tree,这篇文章只考虑Auffix Array的快速构建。Ukkonen 算法参见以上链接。
查找字符串o是否在字符串S中
方案:用S构造后缀树,按在trie中搜索子串的方法搜索o即可。
原理:若o在S中,则o必然是S的某个后缀的前缀。
指定字符串T在字符串S中的重复次数
方案:用S+’$'构造后缀树,搜索T结点下的叶节点数目即为重复次数 (虽然是公共枝,但其实string中位置不同)
原理:如果T在S中重复了两次,则S应有两个后缀以T为前缀,重复次数就自然统计出来了。
最长公共子串 (LCS)
* 自身内部比较 (最长重复子串)
方案:找到最深的非叶节点。 // 深度:从root所经历过的字符个数,最深非叶节点所经历的字符串起来就是最长重复子串
s=abab, 可见最深的非leaf node经过的path是"ab",故,"ab"即是最长重复子串。
* 俩字符串比较
方案:将S1#,S2$作为字符串压入后缀树,找到最深的非叶节点,且该节点的叶节点既有#也有$。
S1=abab, S2=aab,可见,最深的非leaf node经过的path是"ab"。
最长回文 (maximal palindromes)
方案:用S+"$"及其反转字符串+"#"构造后缀树,找到最深的非叶节点,且该节点的叶节点既有#也有$。
Let s = cbaaba$ then sr = abaabc#,
Construct Suffix Array
Drawbacks
- Suffix trees consume a lot of space // 一个字符串的后缀形式毕竟很多
- It is O(n) but the constant is quite big
- Notice that if we indeed want to traverse an edge in O(1) time then we need an array of ptrs. of size |Σ| in each node
That's why Suffix Array. We loose some of the functionality but we save space.
理解后缀数组
Ref: http://cse.unl.edu/~lksoh/Classes/CSCE410_810_Fall03/sup7.html
后缀数组 vs 倒排表
Inverted indices assume that the text can be seen as a sequence of words.
Other queries such as phrases are expensive to solve.
One approach to address this problem is to use the suffix string approach. The index sees the text as one long string.
Each position in the text is a considered as a text suffix (i.e., a string that goes from the text position to the end of the text).
Each suffix is thus uniquely identified by its position.
This type of index allows us to answer efficiently more complex queries.
The main drawbacks of this approach are:
(a) costly construction process,
(b) the text must be readily available at query time,
(c) the results are not delivered in text position order.
Unless complex queries are an important issue, for word-based applications, inverted files still perform better.
后缀数组与后缀树
Suffix arrays are a space efficient implementation of suffix trees.
Also, not all text positions need to be indexed. Index points are selected from the text, which point to the beginning of the text positions which will be retrievable.
以上是11, 19, 28, 33, 40, 50, 60为起点的若干个后缀。如果用后缀树表示,就是如下大概的样子:
Suffix Tree 在 DFS 后就是 Suffix Array。
可见,只是字符串后缀的两种等价的表达形式,即:数据结构不同。
但实际上,只需要记录以下绿色的部分index即可。
Simply an array containing all the pointers to the
text suffixes listed in lexicographical order.
通过这个index array 并结合"原字符串",即可推出所有必要信息。
节省了空间,但失去了一定的功能上的便捷性,比如树结构的快速查找。
后缀数组,需采用二分查找find指定的后缀。
但问题是:
If the suffix array is large, this binary search can
perform poorly because of the number of random disk accesses.
Suffix arrays are designed to allow binary searches
done by comparing the contents of each pointer.
To remedy this situation, the use of supra-indices over the suffix array has been proposed.
后缀数组的应用
最长公共子串 (LCS)
* 自身内部比较 (最长重复子串)
字符串内部比较,后缀树表示时比较方便(见上)。
变为后缀数组后,功能性换取了空间节省,该怎么办?
(1) 可见,从左到右查看最长common的部分即可。
(2) 方便使用并行策略。
* 俩字符串比较
合并后还是采取如上策略即可。
其实,既然保有原字符串,再装备上suffix array这样的类似指针的数组就好了。
suffix tree因为空间大,只需要“遍历”操作即可。
suffix array需通过“遍历with比较”就能达到相同效果。
其他待解决问题的sol思想类似。
Supra-indices
借助skip pointer的思想来加速查询。
Supra-Index相当于提取了文本中的一部分sub-string,
注意,这个(任意的)sub-string其实代表了文本字符串的某个后缀的前缀!
那么,Supra-Index可以快速地初步定位目标的大概区间段,然后在该区间再进行“精细地”二分查找。
快速创建后缀数组
Space Efficient Linear Time Construction of Suffix Arrays - Pang Ko and Srinivas
Video: https://www.youtube.com/watch?v=m2-N853rS6U
Algorithm: Difference Cover modulo 3 - O(n)
Suffix Array <--> BWT Matrix
(1) 后缀Set --(sort)--> 后缀数组 --(Suffix array-1)--> BWT
后缀排序后-->BWT matrix(的一半显示部分,非绿色字体)
BWT matrix:第一列:suffix Array,但记录的是index,而不是char。
BWT matrix:第尾列:BWT,通过suffix array-1获得。例如,6-1=,"BANA]=N
(2) BWT --(C Table) --> char 的顺序性,即: Index for 后缀数组
所以,Suffix Array若能O(n)创建,那么BWT的创建直接由SA转化后即可,故也能O(n)。
实战(O(n))
string = "MISSISSIPPI$",
Tast: construct its suffix array.
Step 1, mark L and S
type | L | S | L | L | S | L | L | S | L | L | L | L/S |
index | 1 | 2 | 5 | 8 | 9 | 12 | ||||||
text | M | I | S | S | I | S | S | I | P | P | I | $ |
distance | 0 | 0 | 1 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 | 4 |
Step 2, create bucket
Bucket | ||||||||||||
代表了顺序性 | $ | I | M | P | S | |||||||
2 | 1 |
Step 3, D lists
D lists | 不考虑 | [2] [1] | |
1 | [9] [3, 6] | 对应的char都是'S',暂没法判断 | |
2 | [10] [4, 7] | 对应的char都是'S',暂没法判断 | |
3 | [5, 8, 11] | 对应的char都是'I',暂没法判断 | |
4 | [12] |
Step 4, S-Substring
S对应的项:2, 5, 8, 12.
其实就是进一步判断, 行。主要还是第行。
2 | 5 | 8 | 全都是I |
3 | 6 | 9 | 9:P 靠前;故不用再判断 |
4 | 7 | 全都是S | |
5 | 8 | 全都是I | |
6 | 9 | 6:S;9:P,故,5靠前 |
结果就是:8, 5, 2
11也是'I',但11是L类,2、5、8是S类,根据规则1:
In one bucket(肯定对应一个char),L类在S类的左边。
Bucket | ||||||||||||
代表了顺序性 | $ | I | M | P | S | |||||||
12 | 11 | 8 | 5 | 2 |
填好的部分。这构成了下一步的起始基础。
Step 5, complete others
Bucket | ||||||||||||
$ | I | M | P | S | ||||||||
12 | 11 | 8 | 5 | 2 | 1 | 10 | 9 | 7 | 4 | 6 | 3 | |
规则2 | 11 | 10 | 7 | 4 | 1 | 9 | 8 | 7 | 4 | 5 |
Finally, Suffix Array: [12, 11, 8, 5, 2, 1, 10, 9, 7, 4, 6, 3]
-----------------------------------------------------------------
关于规则1:
可见,$(字典排序)优先级肯定大于P,故,L类一定在S类前面。
关于规则2
‘小’后缀已比较,且前端加一个char而且这个char一致,那么,
‘小’后缀的比较结果决定‘大’后缀的比较结果。
[IR] Suffix Trees and Suffix Arrays的更多相关文章
- 本人AI知识体系导航 - AI menu
Relevant Readable Links Name Interesting topic Comment Edwin Chen 非参贝叶斯 徐亦达老板 Dirichlet Process 学习 ...
- [Code] 变态之人键合一
目的也比较单纯,选一门语言,走向人键合一. 选了两本书作为操练场:<精通Python设计模式>.<Data Structure and Algorithm in Python> ...
- [Code] 烧脑之算法模型
把博客的算法过一遍,我的天呐多得很,爱咋咋地! 未来可考虑下博弈算法. 基本的编程陷阱:[c++] 面试题之犄角旮旯 第壹章[有必要添加Python] 基本的算法思想:[Algorithm] 面试题之 ...
- [LeetCode] 面试题之犄角旮旯 第叁章
题库:LeetCode题库 - 中等难度 习题:网友收集 - zhizhiyu 此处应为一个简单的核心总结,以及练习笔记. 查找一个数“在不在”?桶排序理论上貌似不错. 回文问题 ----> [ ...
- Suffix array
A suffix array is a sorted array of all suffixes of a given string. The definition is similar to Suf ...
- 后缀数组(suffix array)
参考: Suffix array - Wiki 后缀数组(suffix array)详解 6.3 Suffix Arrays - 算法红宝书 Suffix Array 后缀数组 基本概念 应用:字 ...
- suffix tree
文章出处:http://www.cnblogs.com/snowberg/archive/2011/10/21/2468588.html 3 What is a Suffix Tree Suf ...
- 后缀数组(suffix array)详解
写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...
- cf448B Suffix Structures
B. Suffix Structures time limit per test 1 second memory limit per test 256 megabytes input standard ...
随机推荐
- 2018 OO第一次总结(作业1-3)
第一次作业1.程序分析 (1)OO度量 (2)类图: (3)分析与评价: 这次作业由于作业整体设计难度不大,因此按照去年暑假上的OO先导课老师讲的设计方法很容易实现一个还不错的面向对象式程序,类与类之 ...
- selenium之关于 chromedriver的安装和使用
转自:https://blog.csdn.net/d77808675/article/details/79016271 最近在学习爬虫,用到了selenium 环境:Windows,python3 但 ...
- FXAA,FSAA与MSAA有什么区别?效果和性能上哪个好
而MSAA基本上只对画面中物体的边缘进行放大.混合的抗锯操作,因为边缘是锯齿最明显的地方(注意不是所有的边缘).提取边缘,主要是结合深度技术.MSAA是种硬件AA.我们一般说的4x.8x,就是放大倍数 ...
- 461.汉明距离(c++实现)
问题描述: 两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目. 给出两个整数 x 和 y,计算它们之间的汉明距离. 注意:0 ≤ x, y < 231. 示例: 输入: x = ...
- Android四大组件应用系列——使用BroadcastReceiver和Service实现倒计时
一.问题描述 Service组件可以实现在后台执行一些耗时任务,甚至可以在程序退出的情况下,让Service在后台继续保持运行状态.Service分本地服务和远程服务,Local地服务附在主进程上的m ...
- Android之官方导航栏之Toolbar(Toolbar+DrawerLayout+ViewPager+PagerSlidingTabStrip)
通过前几篇文章,我们对Android的导航栏有了一定的了解认识,本次文章将对Toolbar进行综合应用,主要结合DrawerLayout.ViewPager.PagerSlidingTabStrip一 ...
- Spark:几种给Dataset增加列的方式、Dataset删除列、Dataset替换null列
几种给Dataset增加列的方式 首先创建一个DF对象: scala> spark.version res0: String = .cloudera1 scala> val , , 2.0 ...
- JAVA和C#检测IP地址段是否交叉和获取地址段IP列表的方法
一.说明 我们经常编程时,需要对一个DIDR地段计算其可用IP地址,或者验证某个IP是否被包含在一个地址段中. 二.工具 1.Java 可以使用 cidr-ip-trie库解决. https://gi ...
- 关于input时间框设置了弹出选择就不能手动输入的控制
<input class="Wdate" onclick="WdatePicker({minDate:'#F{$dp.$D(\'startDate\');}',ma ...
- WRI$_ADV_OBJECTS表过大,导致PDB的SYSAUX表空间不足
现象监控发现sysaux表空间使用不断增加,导致表空间不足 查看过程 查看版本: SQL> select * from v$version; BANNER CON_ID ------------ ...