【问题标题】:Generalised suffix tree traversal to find longest common substring广义后缀树遍历找到最长公共子串
【发布时间】:2017-08-19 20:25:21
【问题描述】:

我正在使用后缀树。据我所知,我的 Ukkonen 算法运行正常,可以从任意数量的字符串构建通用后缀树。我现在正在尝试实现一个find_longest_common_substring() 方法来做到这一点。为此,我知道我需要在树中的所有字符串之间找到最深的共享边缘(以字符而不是边缘为深度),并且我已经努力了几天才能正确遍历.

现在我在 C++ 中有以下内容。我将省去我所有的代码,但是为了上下文,我将每个节点的边缘保存在一个名为 outgoing_edges 的 unordered_map 中,并且每个边缘都有一个整数向量 recorded_strings,其中包含标识添加的字符串的整数。边的child 字段是它要去的节点,lr 分别标识它的左边和最右边的索引。最后,current_string_number 是树中的当前字符串数。

SuffixTree::Edge * SuffixTree::find_deepest_shared_edge(SuffixTree::Node * start, int current_length, int &longest) {
    Edge * deepest_shared_edge = new Edge;
    auto it = start->outgoing_edges.begin();
    while (it != start->outgoing_edges.end()) {
        if (it->second->recorded_strings.size() == current_string_number + 1) {
            int edge_length = it->second->r - it->second->l + 1;
            int path_length = current_length + edge_length;
            find_deepest_shared_edge(it->second->child, path_length, longest);
            if (path_length > longest) {
                longest = path_length;
                deepest_shared_edge = it->second;
            }
        }
        it++;
    }
    return deepest_shared_edge;
}

据我所知,在尝试调试时,遍历运行正常,并且正确记录了路径长度并设置了最长。但是,由于我不太明白的原因,在最里面的条件中,deepest_shared_edge 有时似乎会更新到错误的边缘。我怀疑我可能不太明白it->second 在整个递归过程中是如何更新的。但是我不太确定如何解决这个问题。

我知道this 类似的问题,但该方法似乎完全不同,我不太确定它在此处如何应用。

我在此期间主要是为了娱乐和学习,所以我不一定需要工作代码来替换上面的代码 - 伪代码或任何对我感到困惑的地方的解释也一样。

【问题讨论】:

    标签: c++ algorithm tree suffix-tree


    【解决方案1】:

    您对deepest_shared_edge 的处理是错误的。首先,您在函数开始时所做的分配是内存泄漏,因为您从未释放内存。其次,递归调用的结果会被忽略,因此无论找到什么最深的边缘都会丢失(尽管您更新了深度,但您不会跟踪最深的边缘)。

    要解决此问题,您应该将deepest_shared_edge 作为参考参数传递(就像您为longest 所做的那样),或者您可以将其初始化为nullptr,然后检查递归调用的返回值nullptr并适当更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 1970-01-01
      相关资源
      最近更新 更多