'canonize'功能(如下所示,来自Ukkonen的论文)是如何工作的,特别是while循环何时完成?我认为p' - k'的值总是小于p - k的值。我是对还是错?
procedure canonize(s, (k, p)):
1. if p < k then return (s, k)
2. else
3. find the tk–transition g'(s, (k', p')) = s' from s;
4. while p' − k' <= p − k do
5. k = k + p' − k' + 1;
6. s = s';
7. if k <= p then find the tk–transition g'(s, (k', p')) = s' from s;
8. return (s, k).
答案 0 :(得分:8)
canonize
函数的作用是this SA post最后描述的内容,我们考虑这样的情况:
情况如下:
活跃点位于(red,'d',3)
,即距离红色节点的defg
边缘有三个字符。
现在我们按照绿色节点的后缀链接。理论上,我们的主动节点现在是(green,'d',3)
。
不幸的是,该点不存在,因为从绿色节点出来的de
边缘只有2个字符。 因此,我们应用canonize
函数。
它的工作原理如下:
我们感兴趣的边缘的起始字符是d
。该字符在Ukkonen表示法中称为t k 。因此,“找到t k -edge”意味着在绿色节点处找到de
边缘。
该边长度只有两个字符。即(p' - k') == 2
在Ukkonen的符号中。但原始边缘有三个字符:(p - k) == 3
。所以<=
为真,我们进入循环。
我们正在寻找从def
到f
的边缘。这就是p := p + (k' - p') + 1
步骤的作用。
我们前进到de
边缘指向的状态,即蓝色状态。这就是s := s'
的作用。
由于边缘的剩余部分f
不为空(k <= p
),我们会识别出相关的外向边缘(即fg
边缘突然出现节点)。此步骤将k'和p'设置为全新值,因为它们现在引用字符串fg
,其长度(p' - k')现在将为2.
剩余边缘的长度f
,(p - k)现在为1,新活动点的候选边fg
的长度为(p' - k'),是2.因此循环条件
while(p' - k')&lt; =(p - k)do
不再为真,因此循环结束,实际上新的(和正确的)活动点为(blue,'f',1)
。
[实际上,在Ukkonen的表示法中,边缘的结束指针p指向边缘的最终字符的位置,而不是其后面的位置。因此,严格来说,(p - k)是0,而不是1,而(p' - k')是1,而不是2.但重要的不是长度的绝对值,而是两者的相对比较长度。]
最后一些注意事项:
像p和k这样的指针指的是原始输入文本t中的位置。这可能会令人困惑。例如,绿色节点的de
边缘中使用的指针将引用t的某些子串de
,以及fg
边缘中使用的指针在蓝色节点处将引用t的一些子串fg
。虽然字符串defg
必须在t中的某处显示为一个连续字符串,但子字符串fg
也可能出现在其他位置。因此,fg
边缘的指针k 不一定 de
边加上的结束指针p。
当我们决定是否结束循环时,重要的不是绝对位置k或p,而是剩余边的长度(p-k)与长度(p' - k'相比) )当前候选人的优势。
在您的问题,代码段的第4行,有一个拼写错误:它应该是k'
而不是k;
。
答案 1 :(得分:0)
我不得不更改canonize函数,因为它没有正确处理辅助状态。我在'p&lt;之后添加了以下代码k'如果:
if (s == auxiliary)
{
s = root;
k++;
if (p < k)
return;
}
似乎现在正在工作:)