古斯菲尔德描述了用于构造后缀树here的Ukkonen算法,但我很难将他的帐户与给定in jogojapan's SO answer的演示合成,因此,挣扎从Gusfield的描述中得出一个有效的实现。
特别是,我无法将jogojapan描述的主动点实现与Gusfield对Ukkonen算法后缀扩展规则的描述进行整合。
简而言之,我的问题是:Gusfield中的B(beta)&后缀扩展规则的定义是否与jogojapan的回答中的活跃点相对应?
据我所知,活动点指向树中下一个节点插入的位置,这对应于插入后缀,只要它创建一个以叶子结尾的新分支。
在使用他的" Trick 3"中描述的全局索引将Gusfield描述为后缀扩展规则1应用于每个现有叶子后,活动点似乎开始起作用。到目前为止,这似乎与jogojapan的答案一致。
然而,在应用规则1之后应用规则2或规则3时,Gusfield的文本开始逃避我.Gusfield概述了"高级算法"如下:
Construct tree I
For *i* from 1 to *m* - 1 do:
Begin {phase *i* + 1}
For *j* from 1 to *i* + 1
Begin {extension *j*}
Find the end of the path from the root labeled S[*j*..*i*] in the current tree and, if needed, extend that path by adding character S(*i* + 1), thus assuming that string S[*j*..*i*+1] is in the tree.
End;
End;
从这个帐户开始,我想知道在扩展 j = i + 1中会发生什么。如上所述,for循环会一直运行到这个值 j ,但循环体仅指定 j = * i之前的行为。换句话说,似乎继续使用最终扩展的算法将导致某种缓冲区溢出或越界错误。
Gusfield对后缀扩展规则的定义似乎遇到了同样的问题。具体来说,他写道(B代替希腊语测试版):
设S [ j .. i ] = B是S [1 .. i ]的后缀。在扩展 j 中,当>算法在当前树中找到B的结尾时,它扩展B以确保>后缀BS( i + 1)是在树上。
规则1 在当前树中,路径B以叶子结束。也就是说,从标记为B的根开始的路径>延伸到某个叶边缘的末端。要更新>树,字符S( i + 1)将添加到该边缘标签的末尾。
规则2 字符串B末尾没有路径以字符S( i + 1)开始,>但至少有一条带标记的路径从结束B继续。 在这种情况下,创建从B mus结束开始的新叶边缘,并用字符S( i + 1)标记。如果B在边缘内结束,则还必须在那里创建新节点。新边缘结束时的引线>给出数字 j 。
规则3 字符串B末尾的某些路径以字符S( i +> 1)开头。在这种情况下,字符串BS( i + 1)已经在当前树中,因此>(记住在隐式后缀树中,后缀的结尾需要不是>明确标记)我们什么都不做。
同样,似乎省略了扩展 j = i + 1 i + 1的相位。这会对所写规则的应用产生问题,因为它们都依赖于评估B,根据其定义,它不能包括最终扩展而不会产生越界错误:即,如果 j = i + 1且B = S [ j .. i ],然后B = S [ i + 1 .. i ],这是不可能的。
我试过假设B ="" (空字符串)在这种情况下,匹配节点是根节点,但这会产生与活动点指定的插入点冲突的插入点。原因似乎是,鉴于所述的规则和我对 j = i + 1的明显被忽视的情况的假设,B只能指向任何实时实现中的根节点,假设指定的"技巧"跟着。
我的理由如下:
根据定义,后缀树中有 n 后缀,表示长度为 n 的字符串(根据Wikipedia)。 Ukkonen的算法包含 n 阶段,输入字符串中每个字符一个。因此,每个阶段必须添加一个后缀(尽管规则和技巧允许将添加内容推迟到后期阶段)。
为每个阶段 i 执行 i 扩展,从1到 n (即 i <的总和/ em>从1到 n )。因此,存在(基本上)比相位更多的扩展,因此存在后缀。由此可见,后缀扩展名不等于后缀插入。
通过应用规则1,无法插入 ,因为此规则仅使用全局索引跟踪的终端字符更新现有的叶边。
因此,在1.和3之后,根据规则2或3执行所有后缀插入。但每个阶段只能发生一次后缀插入,尽管有< em> i 扩展,因此每个阶段只能插入一个扩展。因此,第i + 1阶段的第一个i扩展根据规则1发生。
现在,如果规则1执行阶段 i + 1的第一个 i 扩展,从而耗尽所有B = [ j]的情况 .. i ],规则2或规则3只剩下一个扩展。但是,通过检查从末尾开始的路径决定应用哪一个扩展但是,如上所述,这是不可能的,在这种情况下将B的末尾假定为根。这样做的结果是来自B的所有插入都必须来自root ,但在规则2中明确规定节点可以从边缘插入。
如果这是正确的,那么Gusfield规则指定的插入点与jogojapan概述的活动点实现所指定的插入点之间存在直接冲突,这样前者可能导致许多后缀被忽略树的。
我的推理是错误的还是我遗漏了文中的内容?是否有可能综合这些方法?
注意:我还没有读过古斯菲尔德的书本,并且只引用了上面引用的pdf,所以我可能会使用过时的文本版本。在任何情况下,我都尝试检查errata,但没有发现与本章有关的内容。
另外,我使用这个visualization tool快速测试一些论文以排除某些可能性。