在Trie中加速单词搜索

时间:2017-02-23 14:33:07

标签: ruby algorithm search trie

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

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

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秒 15个字母输入,一个通配符:3,54秒 15个字母输入,两个通配符:15,59s

网上有许多拼字游戏求解器,它们在1秒内完成这些任务。

问题 如何加快这个过程,所以每次不到1秒钟?我在考虑: a)用C语言编写搜索方法 b)重组Trie所以单词存储为按字母顺序排序的字母(例如快速 - >取消) - 这将减少搜索次数 如果你知道任何更好的方法来完成这项特殊任务,我愿意倾听。 c)将我的Trie切换为哈希表?

1 个答案:

答案 0 :(得分:0)

你应该选择b,用字母顺序存储所有字谜。不重访信件是一个巨大的胜利。

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