我从这个惊人的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,但我不知道何时添加新索引。我们可能会使用活动点但使用后缀链接会变得很棘手。
有人可以解释一下吗?
答案 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
的索引。