【问题标题】:Speeding up word search in a Trie加快 Trie 中的单词搜索
【发布时间】:2017-02-23 14:33:06
【问题描述】:

我需要找到所有可以使用用户指定的字母组成的单词。用户可以使用“?” - 作为通配符(最多 2 个通配符)。最大输入为 15 个字符,包括那些通配符。示例输入:“abcdefghijklm??”。

目前我有 2_700_000 个单词存储在 Trie 中。我是这样看的:

def search_word(node, wildcards, alphabet, tiles, output) 

  output.push(node.full_state) if node.terminal? # append output if its a word
  unless tiles.empty? && wildcards.zero?
    tiles.uniq.each do |tile|
      unless node.walk(tile).nil?  # choose only those letters that could possibly make a word
        next_node = node.walk(tile)
        remaining_tiles = take_away(tiles, tile)
        search_word(next_node, wildcards, alphabet, remaining_tiles, output) 
      end
    end
  end

  if wildcards > 0
    other_letters = take_away(alphabet, tiles.uniq)  # letters that weren't used in previous loop
    other_letters.each do |tile|
      unless node.walk(tile).nil? # only those that could make a word
        next_node = node.walk(tile)
        remaining_tiles = take_away(tiles, tile)
        remaining_wildcards = wildcards - 1
        search_word(next_node, remaining_wildcards, alphabet, tiles, output) 
      end
    end
  end

end

它的作用可以描述为:

def searchword(trie, wildcards, tiles, output):
    if trie is word:
        output.append(trie.word) # or send current letters as arguments to this function

    for each unique tile in tiles:
        if trie has tile:
            searchword(trie[tile], wildcards, (tiles - tile), output)

    if wildcards > 0:
        for each key in trie that has not already been searched in previous loop:
            searchword(trie[key], (wildcards - 1), tiles, output)

速度测试: 15 个字母输入,无通配符:0,45 s 15 个字母输入,一个通配符:3,54 s 15 个字母输入,两个通配符:15,59s

网上有很多拼字游戏解决者,它们可以在 1 秒内完成此类任务。

问题 如何加快这个过程,所以我每次不到 1 秒?我正在考虑: a) 用 C 编写搜索方法 b) 重新组织 Trie,以便将单词存储为按字母顺序排序的字母(例如 fast -> afst)——这将减少搜索次数 如果您知道针对此特定任务的更好方法,我愿意倾听。 c) 将我的 Trie 切换为哈希表?

【问题讨论】:

    标签: ruby algorithm search trie


    【解决方案1】:

    您应该使用选项 b,按字母顺序存储所有字谜。不重读信件是一个巨大的胜利。

    除了不按字母顺序排序。按以下顺序对字母进行排序:etaoinshrdlcumwfgypbvkjxqz。这是最频繁到最不频繁。我们的想法是只查看最少次数的常用字母,而不是一遍又一遍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 1970-01-01
      相关资源
      最近更新 更多