【问题标题】:Fastest way to match substring from large dict从大字典中匹配子字符串的最快方法
【发布时间】:2015-12-28 13:43:15
【问题描述】:

我有一些(通常

有一个 python 字典,其中键是类似格式的字符串,例如'bcccd',密钥长度从 10 到 100 个符号不等。字典有 半百万 个条目。

我需要将我的初始字符串与字典的值相匹配,或者找出字典中没有正确的值。匹配条件:字典键应该在字符串中的某处(严格匹配)。

就计算速度而言,最好的方法是什么? 我觉得应该有一些棘手的方法来散列我的初始字符串和字典键,以应用一些巧妙的子字符串搜索方式(如 Rabin-Karp 或 Knuth-Morris-Pratt)。或者后缀树状结构可能是一个很好的解决方案?

【问题讨论】:

  • 在这种情况下,试一试还不够吗?
  • Python 中的in 运算符是严格匹配的,所以你可以使用它。它也是内置的,因此速度相当快。
  • 字典在这里不起作用,你基本上得到了一个字符串列表(你的键)和更长的字符串。 Aho-Corasick 在这里非常适合 - 特别是如果您的字典或多或少稳定的话。

标签: python algorithm search text substring


【解决方案1】:

刚刚找到了适用于 Python 的 Aho-Corasick 的合理实现 - pyahocorasick。取自页面末尾的示例:

import ahocorasick
A = ahocorasick.Automaton()

for k, v in your_big_dict.iteritems():
    A.add_word(k, v)

A.make_automaton()
for item in A.iter(your_long_string):
    print(item)

【讨论】:

  • 是否有成员函数可以报告构建自动机后的状态数。我很好奇 OP 的 500K(小)模式来自一个小(4?)字母表......
  • .dump().get_stats() 似乎提供了一些信息。但是您必须向 OP 询问他的数据的特征;)
  • 非常感谢!向你们所有人 +1,但出于技术原因,JBernardo 的解决方案更适合我。
  • 在这个问题上很难打败 ahocorasick。这也是我的选择:)
【解决方案2】:
def search(string, dict_search):
    # If those 2 lines are too expensive, calculate them and pass as arguments
    max_key = max(len(x) for x in dict_search)
    min_key = min(len(x) for x in dict_search)

    return set(
        string[x:x+i] 
        for i in range(min_key, max_key+1)
        for x in range(len(string)-i+1)
        if string[x:x+i] in dict_search
    )

跑步:

>>> search('aabbccdcabcbbacdaaa', {'aaa', 'acd', 'adb', 'bccd', 'cbbb', 'abc'})
{'aaa', 'abc', 'acd', 'bccd'}

【讨论】:

  • 你的函数应该已经找到'aaa',所以它可能会丢失搜索字符串的最后一个字符。
  • @AustinKootz 谢谢。它在第二个 for 循环中缺少 +1
【解决方案3】:

您可以使用以下格式:

for key in your_dictionary:
    if key in your_string:
        print(key+' is in both your string and the dictionary. It has the value '+str(your_dictionary[key]))

如果您想以任何方式对此进行更改,请在 cmets 中告诉我,我很乐意更新。

【讨论】:

  • 这种方法有两个问题:1)字符串比dict小很多,所以遍历dict来测试应该比找到要搜索的字符串片段更昂贵。 2)字符串搜索是O(n),而字典搜索是O(1)平均情况。
  • 还有:for key in your_dictionary: 那里没有价值
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 2018-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-07-05
  • 1970-01-01
相关资源
最近更新 更多