【问题标题】:Fastest/Most optimal way to lookup a sequence of letters in a dictionary written in file在用文件写入的字典中查找字母序列的最快/最佳方法
【发布时间】:2017-05-06 17:24:53
【问题描述】:

我有一个字母序列,不一定是一个单词。我还有一个包含大约 6000 个单词的文件。我必须决定字母序列的任何重新排列是否会在文件中生成一个单词。

最快/最佳的方法是什么?如果我无法将整个文件加载到内存中怎么办?如果我可以呢?

我想到了一个 O(N^2) 的解决方案。当然,匹配单个单词不会像单词数量那么大。但无论如何,它可以称为 O(n^2),不是吗?从文件中读取每一行并检查给定的序列和行的长度是否相等。如果是,则计算每个字符的出现次数并匹配它们。

matched_words = []
with open('words.txt') as file:
for line in file:
    if len(line.strip()) == len(letters) and 
      Counter(line.strip()) == Counter(letters):
        matched_words.append(line.strip())
return matched_words

这可行,但有更好的解决方案吗?

【问题讨论】:

  • 你真的不能把 6000 个单词加载到内存中吗?另请注意,要查找字谜,您可以使用排序,例如sorted('dog') == sorted('god').
  • 这是一次性的,还是您打算在明年多次这样做?月?天?毫秒?另外,会有什么变化?是字母序列,还是包含大量单词的文件?正如@jonsharpe 所说,您可以对所有单词进行排序。
  • 这里的Counter 是什么?
  • @jonrsharpe 是的,我可以加载整个文件。但如果我不能呢?我正在寻找相对的优点和缺点。如果是字谜,它仍然至少是 nlog(n) 对吗?所以对于字典中的 n 个单词,n * nlog(n) 仍然是 O(n^2)。我对么? @quamrana 我不明白你的问题。抱歉@JacobIRR Counter 是收藏库中的一个函数
  • 好吧,如果?你为什么不解决你实际遇到的问题,而不是试图为别人寻找解决方案?

标签: python string file dictionary permutation


【解决方案1】:

对于文件中的每个单词,您可以检查sorted(query)==sorted(word)。复杂度为 O(nklogk),其中 n 是单词的数量,k 是单词的长度。
如果您需要查找多个查询,您可以进行一些预计算以使其更快。您可以对文件中的每个单词进行排序,并将它们加载到内存中的集合中并测试集合成员资格。如果您需要查找作为给定字符序列重新排列的实际单词,请加载到 dict{sorted_form: } 并查找每个查询。
您还可以预先计算排序形式的 trie 并将字典单词存储在 trie 节点中。给定一个大小为 k 的查询词,对词进行排序 O(klogk) 并在 O(k) 中查找 trie,以给出每次查找的复杂度 O(k^2*logk)

【讨论】:

  • 排序仍然是 O(nlogn) 对吗?计算单个字符的出现次数是 O(n)。这不是比排序更好吗?顺便说一句,字典中的单词基本上已经排序了。
  • 请不要混淆单词数(n)和每个单词的长度(k)。假设这里的情况是n>>k,那么排序每个单词是klogk,可以像一个常数因子一样去掉,把O(nklogk)当作O(n)。
【解决方案2】:

您的尝试是在正确的轨道上。我们可以通过消除额外的工作来清理它,如下所示。

from collections import Counter
def gen_matches(target, filepath):
    target_count = Counter(target)
    target_len = len(target)
    with open(filepath) as file:
        for line in file:
            word = line.strip()
            if len(word) == target_len and Counter(word) == target_count:
                yield word

如您所见,这些改动很小。我们可以通过只在目标上调用一次Counter()len() 并分配 line.strip() 的输出来节省一些额外的工作,这样我们就不必重复函数调用。

这避免了将整个文件加载到内存中。它也是 O(n),假设我们的常数因子 k(平均单词的长度)远小于单词的数量。在计算机科学意义上,这比比较sorted(word)sorted(target) 快得多;然而,在实践中,比较排序后的单词可能会更快,因为 python 对sorted() 的实现确实非常快。

您可能想尝试两种方法的计时! :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 2011-05-09
    相关资源
    最近更新 更多