📜  Ukkonen的后缀树构造–第2部分(1)

📅  最后修改于: 2023-12-03 15:20:48.395000             🧑  作者: Mango

Ukkonen的后缀树构造–第2部分

本文是关于使用Ukkonen算法构造后缀树的第2部分,前一部分介绍了算法的基本思想和第一步骤的实现。在本文中,我们将讨论第二步骤的实现,即扩展活跃点。

扩展活跃点

在本部分中,我们将讨论如何使用Ukkonen算法扩展活跃点。我们已经在前一部分中介绍了如何在每次添加一个字符到后缀树上时,构造一个新的分支,并更新对应的活跃点。同样,在扩展活跃点时,我们需要对当前的边进行分割,并在树中添加一个新的节点。

在第一步骤中,我们设置了一个全局变量activeNode来存储当前的活跃节点。在扩展活跃点时,我们需要检查当前的边是否已经以当前活跃节点的某个后缀开头,如果是,则我们只需要通过更新某些值来扩展活跃点。否则,我们需要在当前边上分割节点,并将新节点插入到树中。

下面是扩展活跃点的步骤:

  1. 检查当前边是否已经以当前活跃节点的某个后缀开头。如果是,则直接更新某些值。
  2. 否则,在当前边上找到第一个字符c,使得添加字符c到当前边的末尾后,得到的新边的开头就是当前活跃节点的某个后缀。我们将当前边分成两个部分:一个前缀部分,包含所有比c小的字符;一个后缀部分,包含所有比c大的字符。
  3. 在前缀部分上更新信息,并将前缀部分与当前活跃节点连接起来。
  4. 在后缀部分上创建一个新的节点,并将其插入到树中,将其与前缀部分连接起来。

下面是扩展活跃点的Python代码示例:

def extendActiveNode(tree, activeNode, activeLen, i, s):
    split_char = s[i]
    # 寻找第一个字符c,使得添加字符c到当前边的末尾后,得到的新边的开头就是当前活跃节点的某个后缀
    if (activeLen == 0 and tree[activeNode].hasChild(split_char)) or (activeLen > 0 and s[i - activeLen] == tree[activeNode].getEndChar(activeLen - 1)):
        if activeLen > 0:
            tree[activeNode].end[activeLen - 1] = i
        return

    # 分割边,创建新节点
    split_pos = activeNode if activeLen == 0 else tree[activeNode].end[activeLen - 1]
    suffix_node = TreeNode(s, split_pos + 1, len(s))
    suffix_node_id = len(tree)
    tree.append(suffix_node)

    # 更新前缀部分
    tree[activeNode].setEndChar(activeLen - 1, s[i - activeLen])
    tree[activeNode].child[s[split_pos + 1]] = activeNode + 1

    # 将新节点插入到树中
    suffix_node.link = getActiveNode(tree, 0, activeNode)
    tree[getActiveNode(tree, 0, activeNode)].child[s[split_pos + 1]] = suffix_node_id

    # 更新活跃节点
    while activeNode != 0:
        activeNode = getActiveNode(tree, suffix_node.link, activeNode)
        if activeNode == suffix_node.link:
            suffix_node.setEndChar(activeLen - 1, s[i - activeLen])
            break

        # 创建新节点
        new_node = TreeNode(s, i - activeLen, i)
        new_node_id = len(tree)
        tree.append(new_node)

        # 更新信息
        tree[activeNode].child[s[i - activeLen]] = new_node_id
        new_node.child[s[i]] = suffix_node_id

        # 将新节点插入到树中
        tree[new_node_id].link = suffix_node_id

        # 更新活跃节点
        suffix_node = new_node
        suffix_node_id = new_node_id
总结

本文介绍了如何使用Ukkonen算法扩展活跃点,并在树中添加新节点。扩展活跃点是构造后缀树的第2步,它是一个关键步骤,需要仔细处理。在下一篇文章中,我们将讨论如何使用算法的第3步来构造完整的后缀树。