【问题标题】:find most common substring in given string? overlapping is allow在给定的字符串中找到最常见的子字符串?重叠是允许的
【发布时间】:2014-09-29 18:04:30
【问题描述】:

我已经搜索过关于这个问题的帖子。但他们都没有明确的答案。

查找给定字符串中长度为 n 的最常见子字符串的出现。 例如,“deded”,我们将子串的长度设置为 3。“ded”将是最常见的子串,它的出现次数为 2。 很少有帖子建议使用后缀树,时间复杂度为 O(nlgn),空间复杂度为 O(n)。 首先,我不熟悉后缀树。我的想法是使用 hashmap 存储每个长度为 3 的子字符串的出现。时间是 O(n),而空间也是 O(n)。这比后缀树好吗?我应该考虑 hashmap 冲突吗?

额外:如果解决了上述问题,我们如何解决子字符串长度无关紧要的问题。只需找到给定字符串中最常见的子字符串即可。

【问题讨论】:

  • 您的 hashmap 解决方案简单、优雅,并且可以在线性时间/复杂度下工作(如果子字符串长度是固定的)。为什么你觉得性能是个问题?记住,先做对。过早的优化可能会导致您没有可能永远不需要访问的兔子洞。相同的解决方案适用于任何长度的子字符串,但现在复杂性可能成为问题,其严重性取决于子字符串的最大大小。
  • 即使长度不固定,我也没有看到任何复杂性问题。不管检查,你都必须找到所有可能的子字符串,除非你想做一些边缘情况,比如只期望 2 个长度为 5 的字符串的 4 长度子字符串。
  • “deded”最常见的非空子串怎么不是“d”?关于使用散列的复杂度,别忘了计算散列码的复杂度。
  • @greybeard:因为子字符串长度设置为三个。在 OP 的简单情况和第一个示例中,我们只是在寻找长度为 3 的子字符串。

标签: string algorithm substring


【解决方案1】:

如果最常见的子字符串的长度无关紧要(但假设您希望它大于 1),那么最好的解决方案是寻找长度为 2 的最常见的子字符串。您可以使用线性时间的后缀树,如果你查找后缀树,那么它会很清楚如何做到这一点。如果您希望最常见子字符串的长度 M 作为输入参数,那么您可以使用乘加散列在线性时间内散列所有长度为 M 的子字符串,其中您将前一个字符串散列值乘以一个常数,然后添加字符串中下一个最低有效值的值,并取模数模数 P。如果您选择计算字符串整数的模数 P 作为随机选择的素数 P,这样您就可以存储 O(P) 内存,那么如果您假设您的散列没有冲突,那么这将在线性时间内完成。如果您假设您的散列可能有很多冲突,并且子字符串的长度为 M 并且总字符串长度为 N,那么运行时间将是 O(MN),因为您必须检查所有冲突,这是最坏的情况case 可能会检查所有长度为 M 的子字符串,例如,如果您的字符串是全一个字符的字符串。后缀树在最坏的情况下会更好,如果您需要一些细节,请告诉我(但不完全,因为后缀树很复杂),我可以从高层次上解释如何使用后缀树获得更快的解决方案。

【讨论】:

  • 感谢您的建议。为什么需要定义自己的散列函数?我可以只使用(如在 JAVA 中)hashmap 进行散列吗?我很少写散列函数。但是让我知道这是否比使用内置的 hashmap 更有优势。
猜你喜欢
  • 2020-02-23
  • 2021-12-28
  • 2019-07-16
  • 1970-01-01
  • 2017-11-23
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
相关资源
最近更新 更多