Python-查找可以在单词内部找到的所有子词

标签 python algorithm

最终,我想找出英语词典中哪个单词包含最多三个字母的子词。我写了这个算法,但它太慢了,没有用。想知道如何优化它

def subWords(word):
    return set((word[0:i] for i in range(2, len(word)+1))) #returns all subWords of length 2 or greater

def checkDict(wordList, dictList):
    return set((word for word in wordList if word in dictList))

def main():
    dictList = [i.strip() for i in open('wordlist.txt').readlines()]
    allwords = list()
    maximum = (0, list())

    for dictWords in dictList:
        for i in range (len(dictWords)):
            for a in checkDict(subWords(dictWords[i: len(dictWords) + 1]), dictList):
                allwords.append(a)

        if len(allwords) > maximum[0]:
            maximum = (len(allwords), allwords)

        print maximum
        allwords = list()

    print maximum 
main()

最佳答案

您的算法的主要弱点是,对于每个子词,您需要将其与字典中的每个其他词进行比较。你不需要这样做,真的——如果你的单词以“a”开头,你真的不需要查看它是否与以“b”开头的单词匹配。如果下一个字母是“c”,那么你并不真的在意将它与以“d”开头的单词进行比较。那么问题就变成了:“我如何有效地实现这个想法?”

为此,我们可以创建一棵树来表示字典中的所有单词。我们通过获取字典中的每个单词并用它扩展树并在最后一个节点中添加阴影来构建这棵树。

Example Tree

当我们想要测试一个子词是否在这棵树中时,我们只需逐个字母地检查该词并使用这些字母来确定树中的下一个位置(从顶部开始)。如果我们发现我们无处可去,或者在遍历整个子词后我们落在了一个没有阴影的树节点上,那么它就不是一个词。否则,如果我们落在阴影节点上,它就是一个词。这样做的效果是我们可以一次搜索整个词典,而不是一次搜索一个词。当然,这样做的代价是一开始需要进行一些设置,但如果字典中有很多单词,那么付出的代价并不是很大。

嗯,这一切都太棒了!让我们尝试实现它:

class Node:
    def __init__( self, parent, valid_subword ):
        self.parent = parent
        self.valid_subword = valid_subword
        self.children = {}

    #Extend the tree with a new node
    def extend( self, transition, makes_valid_word ):
        next_node = None
        if transition in self.children:
            if makes_valid_word:
                self.children[transition].makes_valid_word = True
        else:
            self.children[transition] = Node( self, makes_valid_word )
        return self.children[transition]

def generateTree( allwords ):
  tree = Node( None, False )
    for word in allwords:
      makes_valid_word = False
      current_node = tree
      for i in range(len(word)):
        current_node = current_node.extend( word[i], True if i == len(word) - 1 else False )
  return tree

def checkDict( word, tree ):
    current_node = tree
    for letter in word:
        try:
            current_node = current_node.children[letter]
        except KeyError:
            return False

    return current_node.valid_subword

然后,稍后:

for word in allWords:
  for subword in subWords(word):
    checkDict(subword)
    #Code to keep track of the number of words found, like you already have

此算法允许您在 O(m) 时间内检查一个单词是否在您的字典中,其中 m 是字典中最长单词的长度。请注意,对于包含任意数量单词的字典,这大致保持不变。您的原始算法是每次检查 O(n),其中 n 是字典中的单词数。

关于Python-查找可以在单词内部找到的所有子词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6933741/

相关文章:

algorithm - 使用 Dijkstra 时如何加权其他因素

python - 证明链表是循环的最快方法?在 python

Python 正则表达式或

python - Python 类的 `__dict__`

python - 查看所有定义的变量

java - 创建线程来运行算法播放器

python - 'sys.argv' 是什么意思?

python - 使用 Launchd : imports not found 运行 Python 脚本

细化算法的C++代码(EVG-thin)

java - 初始猜测的优化是否会使巴比伦法快速求平方根?