8.1 后缀树
一棵后缀树包含一个指定文本的所有后缀,对于在一个长度为N的文本中查找一个长度为M的子字符串,一个后缀树仅仅需要M次比较,而这个比较次数是查找该字符串所需要的最小比较次数。
后缀树有以下特征:一条边可以表示文本的任何非空子串,每个非终端节点,除了根节点,必须至少有两个孩子边,兄弟边表示的子串必须开始于不同的字符。
ababa所对应的后缀树如下所示:
后缀树可以解决很多复杂的字符串编程问题,包括:
1. 查询字符串S是否包含子串S1。主要思想是:如果S包含S1,那么S1必定是S的某个后缀的前缀;又因为S的后缀树包含了所有的后缀,所以只需对S的后缀树使用和Trie相同的查找方法查找S1即可。使用后缀树实现的复杂度同流行的KMP算法的复杂度相当。
2. 找出字符串S的最长重复子串S1。比如abcdabcefda里abc同da都重复出现,而最长重复子串是abc。
3. 找出字符串S1和S2的最长公共子串。注意最长公共子串(Longest CommonSubstring)和最长公共子序列(LongestCommon Subsequence, LCS)的区别:子串(Substring)是串的一个连续的部分,子序列(Subsequence)则是从不改变序列的顺序,而从序列中去掉任意的元素而获得的新序列;更简略地说,前者的字符的位置必须连续,后者则不必。比如字符串acdfg同akdfc的最长公共子串为df,而他们的最长公共子序列是