广义后缀树遍历以查找最长的公共子字符串
Generalised suffix tree traversal to find longest common substring
我正在使用后缀树。据我所知,我让 Ukkonen 的算法正确运行,以从任意数量的字符串构建通用后缀树。我现在正在尝试实现一种find_longest_common_substring()
方法来做到这一点。为此,我知道我需要在树中的所有字符串之间找到最深的共享边缘(在字符方面具有深度,而不是边缘(,并且我已经努力了几天才能正确遍历。
现在我有以下C++。我将省略我的所有代码,但为了上下文,我将每个节点的边缘保留在一个名为outgoing_edges
的unordered_map中,并且每个边缘都有一个整数向量,recorded_strings
包含标识添加字符串的整数。边的child
字段是它要去的节点,l
和r
分别标识其最左边和最右边的索引。最后,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
在整个递归过程中是如何更新的。然而,我不太确定如何解决这个问题。
我知道这个类似的问题,但这种方法似乎足够不同,我不太确定它在这里如何应用。
我主要是为了好玩和学习,所以我不一定需要工作代码来替换上述内容 - 伪代码或只是对我困惑的地方的任何解释也一样。
你对deepest_shared_edge
的处理是错误的。 首先,您在函数开始时执行的分配是内存泄漏,因为您永远不会释放内存。 其次,递归调用的结果被忽略,因此它找到的任何最深的边缘都会丢失(尽管您更新了深度,但不会跟踪最深的边缘(。
要解决此问题,您应该将deepest_shared_edge
作为引用参数传递(就像longest
一样(,或者您可以将其初始化为nullptr
,然后检查递归调用的返回值以获取nullptr
并适当更新它。
- 使用正则表达式regex_search在字符串中查找字符串
- 按类型与字符串查找对象
- 使用C RTTI(内置)通过字符串查找功能指针
- 关于获取行和字符串查找函数的问题
- 字符串查找方法找不到第一字母
- C++ 字符串.查找()
- 遇到字符串::查找的问题
- 将一个数组作为子字符串查找到另一个数组中
- 字符串查找第一个非的 C++ 问题
- 如何将通配符与字符串::查找一起使用
- 字符串::查找问题 (C++)
- 性能标准::strstr vs. 标准::字符串::查找
- C++字符串::查找崩溃应用程序
- 使用字符串查找单词的正确方法是什么
- 如何在<string>没有 std::string 中介的情况下制作一个支持通过 C 字符串查找的集合?
- 使用C++根据行中的第一个字符串查找行(仅一个)
- Borland字符串::查找bug
- std::map如何通过字符串查找元素
- 字符串查找函数返回奇数
- 如何使用子字符串查找数字行的正确部分