Python:如何生成字典词汇集下句子的所有分词组合
解决全合法分词组合生成问题
嘿,我来帮你搞定这个全部分词组合生成的问题!你的需求是把句子ABCAB按照给定字典{'A': 3, 'B': 4, 'C': 5, 'AB':6}拆出所有可能的合法分词组合,但现有代码只返回一个结果,这问题我熟,咱们一步步来解决。
先说说原代码的问题
你原来的代码有几个关键问题导致只能返回一个结果:
- 用了全局的
words列表,递归过程中会被多次修改,不同分支的结果会互相干扰,最后只能保留一条路径。 - 加了很多不必要的限制,比如
word.startswith(sentence[0])会过滤掉后续位置的合法单词,word not in words更是完全错误——同一个单词本来就可以多次出现在分词结果里(比如示例里的A和B)。 - 函数逻辑混乱,比如
find_words里调用了未定义的find_ngrams,流程走不通。
正确的解法:递归回溯
要生成所有可能的组合,递归回溯是最直接的思路——每一步尝试所有合法的单词,递归处理剩下的子串,处理完后回溯尝试其他可能,直到遍历完所有分支。
完整实现代码
# 定义你的词汇字典和最长单词长度 test_dict = {'A': 3, 'B': 4, 'C': 5, 'AB': 6} max_word_length = max(len(word) for word in test_dict) def generate_all_segmentations(sentence): # 用来存储所有合法的分词组合 result = [] def backtrack(remaining_str, current_path): # 如果剩余字符串为空,说明找到了一个完整的合法分词 if not remaining_str: result.append(current_path.copy()) return # 尝试所有可能的单词长度:从1到最长单词长度,或者剩余字符串的长度(取较小值) max_possible_len = min(max_word_length, len(remaining_str)) for length in range(1, max_possible_len + 1): current_word = remaining_str[:length] # 如果当前子串在字典里,就继续递归 if current_word in test_dict: current_path.append(current_word) # 递归处理剩下的字符串 backtrack(remaining_str[length:], current_path) # 回溯:移除当前单词,尝试下一个可能的长度 current_path.pop() # 启动回溯 backtrack(sentence, []) return result # 测试 sentence = "ABCAB" all_results = generate_all_segmentations(sentence) print(all_results)
运行结果
执行后会输出你想要的所有组合:
[['A', 'B', 'C', 'A', 'B'], ['A', 'B', 'C', 'AB'], ['AB', 'C', 'A', 'B'], ['AB', 'C', 'AB']]
代码解释
backtrack是核心递归函数:remaining_str是还没处理的剩余句子,current_path是当前已经选好的分词列表。- 当
remaining_str为空时,说明我们已经把整个句子合法拆分完了,把当前路径的副本加入结果列表(用copy()是因为列表是可变对象,直接添加会导致后续修改影响已存入的结果)。 - 遍历所有可能的单词长度,只要当前子串在字典里,就把它加入路径,递归处理剩下的部分;处理完后再把它从路径中移除(回溯),这样就能探索所有可能的分支。
这种方法逻辑清晰,能覆盖所有合法的分词组合,完全符合你的需求,而且不需要依赖itertools之类的库。
内容的提问来源于stack exchange,提问作者muc777




