如何使用后缀树查找所有匹配子字符串的索引?

时间:2014-06-11 18:41:29

标签: c++ algorithm suffix-tree

我从这个惊人的answer创建了一个后缀树。它就像一个魅力!

现在,如果我寻找" cat"在"这只猫是一只漂亮的猫",它将返回5作为" cat"首次出现至于开始指数5。

但我无法找到一种方法来跟踪要创建的算法中的所有后缀。所以基本上,我可以找到第一个匹配的索引,但不是所有不同的匹配。

现在,我有:

class Edge
{
    int textIndexFrom;
    Node* nodefrom;
    Node* nodeTo;
    int textIndexTo;
}

class Node
{
    std::map<char,Edge*> m_childEdges;
    Edge* m_pParentEdge;
    Node* m_pLinkedNode;
}

我只是将相关变量放在上面的代码中。为了存储不同的起始位置,我想在Edge中需要std :: vector,但我不知道何时添加新索引。我们可能会使用活动点但使用后缀链接会变得很棘手。

有人可以解释一下吗?

2 个答案:

答案 0 :(得分:1)

我假设您为字符串 S $ 构建了后缀树,其中 $ S 中不存在的特殊字符。 $ char确保每个后缀在树中都有自己的叶子。 S 中单词 w 的出现次数是 w 子树中的叶子数。

我认为在每个边/节点中存储所有起始位置都需要二次存储器。例如,如果 T 碰巧是完全平衡的二叉树,那么在0级(根)上你有 n 条目,在1级你有 2 * n / 2 条目等。总结后,它给我们 n ^ 2 。它需要证明,如果我错了,请纠正我。

相反,我认为最好将所有叶子保留在列表中,以便它们出现在树的dfs遍历中(如果绘制树的图片,则从左到右)。并且在每个节点 v 中保留2个指向该列表元素的指针。首先应指向 v 子树的第一片叶子,然后指向 v 子树的最后一片叶子。所有这些都可以通过简单的dfs程序来计算。现在,如果例如'cat'恰好位于某个边缘的中间,则通过该边缘到某个节点 v 并从该节点获取叶子。此外,在每个叶子中,您应该存储从根到该叶子的路径长度。它将帮助您找到特定“猫”出现的位置。

答案 1 :(得分:0)

遍历整个cat子树。该子树中的每个叶子对应一个以cat开头的后缀。如果您知道到目前为止匹配的字符串的长度和字符串的长度,每次遇到一个叶子时,您可以进行减法以找到相应出现的cat的索引。