两个Trie节点之间的最短路径

acu*_*joe 8 javascript python sorting algorithm performance

这是一个双重问题,因为我对如何最有效地实现这一点缺乏想法.

我有一个150,000字的字典,存储在Trie实现中,这是我的特定实现: 特里 - 图

向用户提供两个单词.目标是从起始单词到结束单词找到其他英语单词的最短路径(由一个字符改变).

例如:

开始:狗

结束:猫

路径:狗,点,婴儿床,猫

路径:狗,Cog,日志,沼泽,机器人,婴儿床,猫

路径:狗,美国能源部,乔,喜悦,Jot,婴儿床,猫


我当前的实现经历了几次迭代,但最简单的我可以提供伪代码(因为实际代码是几个文件):

var start = "dog";
var end = "cat";
var alphabet = [a, b, c, d, e .... y, z];
var possible_words = [];

for (var letter_of_word = 0; letter_of_word < start.length; letter_of_word++) {
  for (var letter_of_alphabet = 0; letter_of_alphabet < alphabet.length; letter_of_alphabet++) {
      var new_word = start;
      new_word.characterAt(letter_of_word) = alphabet[letter_of_alphabet];
      if (in_dictionary(new_word)) {
          add_to.possible_words;
      }
  }  
}

function bfs() {
    var q = [];
    ... usual bfs implementation here ..
}
Run Code Online (Sandbox Code Playgroud)

的已知,:

  • 一个开始的单词和一个完成的单词
  • 单词长度相同
  • 单词是英语单词
  • 那里可能没有路径


题:

我的问题是我没有一种有效的方法来确定一个潜在的单词,可以在不强制字母表的情况下尝试并根据字典检查每个新单词.我知道有可能使用前缀更有效的方法,但我无法弄清楚一个正确的实现,或者不只是加倍处理.

其次,如果我使用不同的搜索算法,我已经将A*和Best First Search视为可能性,但那些需要权重,我没有.

思考?

Ton*_*roy 4

根据评论中的要求,说明我通过在整数位中编码链接词的意思。

在 C++ 中,它可能看起来像......

// populate a list of known words (or read from file etc)...
std::vector<std::string> words = {
    "dog", "dot", "cot", "cat", "log", "bog"
};

// create sets of one-letter-apart words...
std::unordered_map<std::string, int32_t> links;
for (auto& word : words)
    for (int i = 0; i < word.size(); ++i)
    {
        char save = word[i];
        word[i] = '_';
        links[word] |= 1 << (save - 'a');
        word[i] = save;
    }
Run Code Online (Sandbox Code Playgroud)

上述代码运行后,links[x]-where xis a word with a letter replacement with a underscore a la d_g- 检索一个整数,表示可以替换下划线的字母组成已知单词。如果最低有效位打开,则“dag”是已知单词,如果最低有效位的下一个打开,则“dbg”是已知单词等等。

直观上,我希望使用整数来减少用于链接数据的总体内存,但是如果大多数单词每个只有几个链接单词,那么存储一些索引或指向这些单词的指针实际上可能会使用更少的内存 - 如果您这样做会更容易不习惯按位操作,即:

std::unordered_map<std::string, std::vector<const char*>> links;
for (auto& word : words)
    for (int i = 0; i < word.size(); ++i)
    {
        char save = word[i];
        word[i] = '_';
        links[word].push_back(word.c_str());
        word[i] = save;
    }
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,您都会得到一个图表,将每个单词与它可以通过单字符更改转换成的单词链接起来。然后,您可以应用Dijkstra 算法的逻辑来查找任意两个单词之间的最短路径。

  • @acupajoe:不客气。祝其余的实施顺利。干杯。 (2认同)