为什么我们在实施suffix tree时需要在原始字符串中添加“$”?
答案 0 :(得分:1)
我怀疑这是为了穿越目的。当你从后缀树生成某些东西时,你需要知道你是否在一个字符串完成的节点上,如果没有,那么你知道你必须继续前进。查看后缀树提供线性时间解决方案的longest common substring,您需要$
个标记来确定您已到达字符串终止的节点。你无法在A-NA
之后完成。
来自维基百科
答案 1 :(得分:1)
当使用特定的构造算法时,在字符串的末尾附加一个(甚至更多)特殊字符可能有特殊原因 - 在后缀树和后缀数组的情况下。
但是,后缀树的最基本的根本原因是后缀树的两个属性的组合:
这意味着您可能会遇到一个边缘标签是另一个边缘标签的情况:
这里的想法是右边的黑色节点是叶节点,即后缀在这里结束。但是,如果文本具有后缀aa
,则单个字符a
也必须是后缀。但是我们无法存储后缀在第一个a
之后结束的信息,因为aa
形成树的一个连续边(上面的属性1)。我们必须引入一个中间节点,我们可以在其中存储信息,如下所示:
但由于属性2,这将是非法的:除非有分支点,否则必须存在内部节点。
如果我们可以保证文本的最后一个字符是整个字符串中不存在的字符,那么问题就解决了。美元符号通常用作符号。
显然,如果最后一个字符出现在其他地方,则字符串末尾不可能有任何重复(例如aa
,或者甚至更复杂的字符,如abcabc
),因此,不会发生非分支内部节点的问题。在上面的示例中,将$
放在字符串末尾的效果是:
现在有三个后缀:aa$
,a$
和$
,但没有一个是另一个的前缀。显然,这意味着我们需要引入一个内部节点,现在总共有三个叶子。所以,可以肯定的是,这样做的好处是不,我们可以节省空间或提高效率。这只是保证上述两个属性的一种方法。当我们证明后缀树的某些有用特性时,这些属性很重要,包括它的内部节点数在字符串长度上是线性的(如果允许非分支内部节点,则不能prove this)。
这也意味着在实践中,您可能会使用不同的方式来处理作为其他后缀前缀的后缀,以及非分支内部节点。例如,如果您使用众所周知的Ukkonen算法来构造树,则可以在不添加唯一字符的情况下执行此操作;你必须确保最后,在最后一次迭代之后,将非分支内部节点放在每个隐含后缀的末尾(即每个后缀以边缘中间结束)。
再次,在构造后缀树或数组之前,将$
放在文本末尾可以有进一步的,非常具体的原因。例如,在基于DC(差异覆盖)原则的后缀数组的构造算法中,必须在字符串的末尾放置两个$
符号,以确保即使字符串的最后一个字符也是完整的字符trigram,因为算法基于trigram排序。此外,在必须以特殊方式解释唯一$
字符时,存在特定情况。对于Ukkonen构造算法,$
是唯一的就足够了;对于DC后缀数组算法,除了唯一性之外,$
在字典上比所有其他字符小,并且在基于后缀树的圆形字符串切割算法(最近提到here)中是必要的实际上有必要将$
解释为按字典顺序最大的字符。