【问题标题】:Optimal way to replace substrings given a table给定表替换子字符串的最佳方法
【发布时间】:2021-05-18 20:52:34
【问题描述】:

在给定表格的情况下,替换单词列表中的子字符串的最佳/最佳方式是什么。假设单词的数量可能非常大。此外,可以假设每个单词只需要 1 个匹配项或只有 1 个匹配项。如果找到匹配项,则无需替换甚至检查其他子字符串。

我目前的解决方案是蛮力,取 O(nmk):

words = ['dfacatlgajd', 'sdfalafjump', 'adfasfhagl']

conversion = {'cat': 'dog',
              'car': 'zoom',
              'jump': 'over'}

new_words = []
for word in words:
    updated = False
    for k, v in conversion.items():
        if k in word:
            new = word.replace(k, v)
            updated = True
            new_words.append(new)
            break
    if not updated:
        new_words.append(word)

print(new_words)

输出:

['dfadoglgajd', 'sdfalafover', 'adfasfhagl']

【问题讨论】:

  • 您可以使用 for .. else 构造而不是保留标志 (updated),否则您的代码就可以了。
  • 寻找更优化的解决方案。我必须用这个实现多次迭代一个词
  • re.sub()repl函数一起使用。
  • @martineau 这也是我的第一个想法,但是在测试它时,它的运行速度比原始代码慢得多。
  • 您是否使用了匹配任何子字符串的(单个)正则表达式模式?

标签: python algorithm performance optimization


【解决方案1】:

如果文本长度为 n,要查找的单词集总长度为 m,并且这些单词在文本中出现 k 次,则可以使用 O(m+n+k) 时间找到所有出现次数Aho-Corasick algorithm。如果您通过写出新版本的字符串来执行替换,这只会增加与其总长度成正比的时间。

一种不太复杂但几乎同样快速的方法是应用Rabin-Karp algorithm 来查找所有出现的same-length 单词。您将需要重新运行该算法(或通过维护多个不同长度的哈希来交叉运行它)以处理不同长度的单词。

【讨论】:

    【解决方案2】:

    我不确定这是否完全是一个答案,但代码块不适合 cmets。您可以通过在每个循环开始时将 new_word 分配给 word 来避免条件变量和标志变量,然后在需要时重新分配它:

    new_words = []
    for word in words:
        new_word = word
        for k, v in conversion.items():
            if k in word:
                new_word = word.replace(k, v)
                break
        new_words.append(new_word)
    

    它似乎运行稍微快,但这可能只是测量差异。 (在渐近复杂度方面并没有什么不同,但条件检查确实需要时间。)我个人也觉得它更容易阅读,但你的里程可能会有所不同。

    【讨论】:

      猜你喜欢
      • 2011-10-16
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多