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

how to find the indexes of all matching substring using suffix tree?

本文关键字:字符串 索引 后缀 何使用      更新时间:2023-10-16

我根据这个惊人的答案创建了一个后缀树。这招真管用!

现在,如果我在"This cat is a pretty cat"中查找"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,但我不知道何时添加新索引。我们可以使用活动点,但是使用后缀links,这就变得很棘手了。

有人能解释一下吗?

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

我认为在每个边/节点中存储所有起始位置将需要二次内存。例如,如果T恰好是完全平衡的二叉树,那么在第0级(根)你有n项,在第1级你有2 * n/2项,以此类推。求和后得到n^2。这需要证明,所以如果我错了,请纠正我。

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

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