【问题标题】:Most efficient way to remove substrings from an array of strings从字符串数组中删除子字符串的最有效方法
【发布时间】:2015-11-11 07:23:25
【问题描述】:

注意:这个问题与 Python 无关。我这里只是用它来代替伪代码。

给定一个数组A 包含平均长度为M 的N 字符串,我想创建一个新数组B,它只包含A 中不是子字符串(或相同)的字符串复制)A 中的任何其他字符串。这是一个例子:

A = [ 'foo', 'bar', 'foobar', 'foobar' ]
B = [ 'foobar' ]

我正在寻找在时间复杂度方面最有效的方法。天真的方法看起来像这样

B = []
for i in range(0, len(A)):
    noSubstring = True
    for j in range(i + 1, len(A)):
        if A[i] in A[j]:
            noSubstring = False
            break
    if noSubstring:
        B.append(A[i])

时间复杂度为O(N^2 * M^2)。有什么办法可以加快速度吗?

我一直在考虑使用专用数据结构来有效地编码和重用字符串序列。例如,如果我想删除只是数组中另一个字符串的前缀的字符串,我可以创建一个 trie / 前缀树 (O(N*M)),然后收集所有叶元素(另一个 O(N*M))。然而,到目前为止,我未能使这种方法适应更普遍的子字符串问题。

【问题讨论】:

标签: python algorithm performance substring


【解决方案1】:

首先消除所有重复项。这很容易通过在迭代数据时使用哈希表并存储已经看到的字符串来实现。 (如果您担心哈希表的最坏情况,您可以使用trie 或排序和迭代以过滤掉重复项)

过滤掉所有重复项后,为所有剩余的字符串创建一个suffix-tree。
创建后缀树后,对于每个字符串,检查它是否作为某个字符串的后缀而存在,而该字符串不是它自己。这是通过遵循后缀树上从根到字符串结尾的路径来完成的,如果您唯一的选择是完全相同的字符串,则它不是子字符串(否则 - 它是)。

时间复杂度:

  • 过滤掉骗子:O(n*m)
  • 理论上构建后缀树 O(n*m),但实际上是在 O(n*mlog(m)) 中完成的。
  • 然后检查每个字符串是 O(m),重复 n 字符串是 O(nm)

总复杂度为O(n*mlog(m))

【讨论】:

  • Filtering out dupes - Hashtable 方法理论上是 O(n),对吧?
  • @thefourtheye O(nm),您需要阅读所有字符串,并且每个字符串都需要 O(m) 时间。它也可以通过排序来完成,如果您担心哈希的最坏情况行为,甚至可以从字符串中创建一个 trie。
  • 我认为在这种情况下,后缀数组的内存效率会更高。它将检查阶段从 O(nm) 增加到 O(nm log m),但由于构造本身已经很复杂,所以这不是问题。
猜你喜欢
  • 2015-08-16
  • 2010-11-10
  • 1970-01-01
  • 2012-12-18
  • 2011-01-11
  • 1970-01-01
  • 2019-09-08
  • 1970-01-01
相关资源
最近更新 更多