我有一系列字母,不一定是一个字。我还有一个包含大约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
这有效,但是有更好的解决方案吗?
答案 0 :(得分:0)
对于文件中的每个单词,您可以检查sorted(query)==sorted(word)
。复杂性将是O(nklogk),其中n是单词的数量,k是单词的长度
如果您需要查找多个查询,可以进行一些预先计算以使其更快。您可以对文件中的每个单词进行排序,并将它们加载到内存集中并测试集合成员资格。如果您需要查找给定字符序列重排的实际单词,请加载到dict {sorted_form:}并查找每个查询。
您还可以预先计算一系列已排序的表单,并将字典单词存储在trie节点中。给定一个大小为k的查询字,将单词O(klogk)排序并在O(k)中查找到trie,以便在每次查找O(k ^ 2 * logk)时给出复杂性
答案 1 :(得分:0)
您的尝试是在正确的轨道上。我们可以通过以下方式消除额外的工作来清理它。
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()的输出来节省一些额外的工作,这样我们就不必重复函数调用。 / p>
这可以避免将整个文件加载到内存中。它也是O(n),假设我们的常数因子k(平均字的长度)远小于字数。从比较sorted(word)
和sorted(target)
开始,这在计算机科学意义上是渐近的更快;但是,实际上,比较排序的单词可能会更快,因为python的sorted()
实现确实非常快。
您可能想尝试两种方法的计时! :)