我天真地想象我可以构建一个后缀trie,在其中我为每个节点保留一个访问计数,然后计数大于1的最深节点就是我要寻找的结果集。
我有一个非常长的字符串(数百兆)。我有大约1 GB的RAM。
这就是为什么用计数数据构建后缀特里在空间方面效率太低而无法为我工作的原因。引用维基百科的后缀树:
存储字符串的后缀树通常比存储字符串本身需要更多的空间。 每个边缘和节点中的大量信息使后缀树变得非常昂贵,在良好的实现中会消耗源文本的内存大小的大约十到二十倍。后缀数组将该要求减少到四分之一,并且研究人员一直在寻找较小的索引结构。
存储字符串的后缀树通常比存储字符串本身需要更多的空间。
每个边缘和节点中的大量信息使后缀树变得非常昂贵,在良好的实现中会消耗源文本的内存大小的大约十到二十倍。后缀数组将该要求减少到四分之一,并且研究人员一直在寻找较小的索引结构。
那是维基百科对树的评论,而不是特里。
如何在如此大量的数据中并在合理的时间内(例如,在现代台式机上不到一个小时)找到较长的重复序列?
(一些维基百科链接避免人们将它们发布为“答案”:字符串算法,尤其是最长重复子字符串问题;-))
执行此操作的有效方法是创建子字符串的索引,并对它们进行排序。这是O(n lg n)运算。
BWT压缩执行此步骤,因此这是一个很好理解的问题,并且存在基数和后缀(要求O(n))排序实现,因此使其尽可能高效。仍然需要很长时间,大文本可能要花费几秒钟。
如果你想使用的工具代码,C ++ std::stable_sort()进行 多 优于std::sort()自然语言(和比C的要快得多qsort(),但出于不同的原因)。
std::stable_sort()
std::sort()
qsort()
然后访问每个项目以查看其与相邻项目的公共子串的长度为O(n)。