我们有一个字符串。
ABAEABABEABE
现在我们必须检查是否存在一个子字符串,接下来是另一个子字符串,它与第一个子字符串完全相同。
在这个例子中:
ABAEAB的 ABE ABE
ABE之后是ABE,这是两个相同的子串。
在这个例子中:
AAB
它只是A,因为A后面是另一个A.
在这个例子中:
ABCDEFGHIJKLMNO
没有这样的子串,所以答案是否。
我只设法找到一个运行在O(n ^ 2)的算法。这是哈希及其前缀。然后,对于每个字母,我们简单地展开并检查以该字母结尾的所有单词。有n个字母。我们需要扩展它n次。所以它是O(n ^ 2)。我相信应该有一个针对这个问题的O(n log n)算法。
有没有人有更好的主意?
答案 0 :(得分:2)
我想你想要这个模式之后可能的最长子串。
要做的第一件事是构建输入字符串的后缀树。使用Ukkonen's algorithm,这是 O(n)。
现在,您提供的条件如何在后缀树中翻译?首先,您正在寻找重复子串 [1] 。 重复的子字符串将显示为后缀树的内部节点。从 n -char字符串构建的后缀树中的The maximum number of nodes是 2n - 1 。
您可以使用它们的长度(字符数)构建包含此类重复子字符串的Max-Heap。 你 NOT 保持长度优于 N / 2 的子串(参见[1])。这是 O(N),其中 N 是后缀树的内部节点数。对于任何后缀树:
0≤ N ≤ n - 2
现在,您从优先级队列中取出最大值并处理您获得的内部节点 i :
让 n 为查询字符串的长度。
因此,整体最坏情况的复杂性是上述的总和,并且是 O(n².log(n))。
我制作了上面的算法...因此它不是最理想的,如果你足够勇敢,你可以通过描述线性时间算法的this paper!无论如何,后缀树是这个问题的关键,所以我建议你仔细研究它们。
[1] :警告,重复的子串可能会部分重叠!
[2] :实际上,最糟糕的情况复杂性比这个非常天真的上限要好,但我不知道如何证明它(还有?!)。例如,如果有 n - 2 内部节点,则意味着原始字符串由 n 出现的相同字符组成。在这种情况下,我们检查的第一个子字符串是match =>它是O(n.log(n))。
[3] :如果我们通过常规排序( O(n.log(n))替换堆构造,最后的比较步骤将在< em> O(n²)而不是 O(n².log(n)) ...降低 O(n.log(n))之间的总体复杂度< / em>(由于排序步骤)和 O(n²)。
答案 1 :(得分:0)
这个问题可以通过“分而治之”的Main-Lorentz算法来解决:
Michael Main,Richard J. Lorentz。用于查找字符串中所有重复的O(n log n)算法[1982]
修改:algorithm description and C++ implementation in Russian(可能会使用Chrome浏览器进行翻译)
还存在linear-time algorithm(不了解实际实施)