【发布时间】:2016-03-17 03:59:18
【问题描述】:
我需要编写一个程序,该程序将带有字典和任意字符串的文件作为输入,然后输出该字典中构成给定字符串的字谜的所有单词组合。
例如,使用英语中最流行的 100 个单词和字符串 "i not work",我应该得到类似 [' on it work', ' into work', ' not i work', ' know or it', ' work it no', ' to work in'] 的内容。
问题是我的程序效率太低了:字典中有 100 个单词,字符串长度的实际限制是 7 个字符,之后的所有内容都需要很长时间。我尝试寻找与此事相关的各种算法均无济于事。
这是我搜索字谜的方法:
def sortstring(string):
return ''.join(sorted(string))
def simplify(all_strings):
possible_strings = defaultdict(list)
for string in all_strings:
possible_strings[sortstring(string).strip()].append(string)
return possible_strings
def generate(database, length,curstring="", curdata=set()):
if len(curstring.replace(" ", "")) > length:
return set()
if len((curstring).replace(" ", "")) == length:
return curdata.union(set([curstring]))
for i in database:
if len((curstring+i).replace(" ", "")) <= length:
curdata = curdata.union(generate(database.difference(set([i])),
length, curstring+" "+i, curdata))
database = database.difference(set([i]))
return curdata
def analyse(database, input_string):
cletters = countstring(input_string)
strings = simplify(generate(database, cletters))
data = list()
sorted_string = sortstring(input_string).strip()
if sorted_string in strings.keys():
data = strings[sorted_string]
return len(strings.values()), data
def countstring(string):
a = countletters(string)
return sum(a.values())
def countletters(string):
result = {}
for i in ascii_lowercase:
result[i] = string.count(i)
return result
谁能提出改进的方法?尽管我认为我使用的算法应该被完全抛弃,因为它的复杂性似乎太高了,因为它太慢了。 以防万一:该程序应该足够高效以支持数万个单词和多达数十个字符的字符串的字典。这比我做的要好得多。
【问题讨论】:
-
几个测试:用2个字母的字符串,生成时间为0.00085s,用3个字母的字符串,生成时间为0.0039s,用4个字母的字符串,生成时间为0.018s,5个字母串,生成时间0.05s,6个字母串,生成时间0.48s,7个字母串,生成时间4.2s。
-
首先编写一个函数,识别所有可以由字符串字母组成的单词,然后在回溯算法中使用这个函数。
-
一种树遍历。空字符串是根。字典中可以由字母组成的单词是儿童。当您访问一个节点时,该节点的子节点是可以由剩余字母组成的单词。任何这样的词也会出现在上一级的可能词列表中——所以你应该能够很快地分辨出哪些词仍然是可能的。如果你到达一个节点,其中有剩余的字母不能组成任何单词——回溯。如果你到达一个没有字母的节点——从根到那个节点的路径就是你寻找的字谜之一。
-
您不必在每个阶段从头开始重新生成列表——当您沿着树向下移动时,您会丢弃可能的单词,而不是添加新单词。整个字典只需要处理一次。
-
我美化了你的代码。缺少空白伤害了我过度敏感的眼睛。
标签: python optimization combinations anagram