7.8.构建字梯图

我们的第一个问题是弄清楚如何将大量的单词集合转换为图。 如果两个词只有一个字母不同,我们就创建从一个词到另一个词的边。如果我们可以创建这样的图,则从一个词到另一个词的任意路径就是词梯子拼图的解决方案。 Figure 1展示了一些解决 FOOLSAGE 字梯问题的单词的小图。 请注意,图是无向图,边未加权。

7.8.构建字梯图.figure1

Figure 1

我们可以使用几种不同的方法来创建解决这个问题的图。假设我们有一个长度相同的单词列表。作为起点,我们可以在图中为列表中的每个单词创建一个顶点。为了弄清楚如何连接单词,我们可以比较列表中的每个单词。比较时我们看有多少字母是不同的。如果所讨论的两个字只有一个字母不同,我们可以在图中创建它们之间的边。对于小的列表,这种方法会正常工作;然而假设我们有一个 5,110 词的列表。粗略地说,将一个字与列表上的每个其他词进行比较是

 7.8.构建字梯图  - 图2。对于5110 个词, 7.8.构建字梯图  - 图3 是超过2600万的比较。

我们可以通过以下方法做得更好。假设我们有大量的桶,每个桶在外面有一个四个字母的单词,除了标签中的一个字母已经被下划线替代。例如,看 Figure 2,我们可能有一个标记为 “pop” 的桶。当我们处理列表中的每个单词时,我们使用 “\” 作为通配符比较每个桶的单词,所以 “pope” 和 “pops “ 将匹配 ”pop_“。每次我们找到一个匹配的桶,我们就把单词放在那个桶。一旦我们把所有单词放到适当的桶中,就知道桶中的所有单词必须连接。

7.8.构建字梯图.figure2

Figure 2

在 Python 中,我们使用字典来实现我们刚才描述的方案。我们刚才描述的桶上的标签是我们字典中的键。该键存储的值是单词列表。 一旦我们建立了字典,我们可以创建图。 我们通过为图中的每个单词创建一个顶点来开始图。 然后,我们在字典中的相同键下找到的所有顶点创建边。 Listing 1 展示了构建图所需的 Python 代码。

  1. from pythonds.graphs import Graph
  2. def buildGraph(wordFile):
  3. d = {}
  4. g = Graph()
  5. wfile = open(wordFile,'r')
  6. # create buckets of words that differ by one letter
  7. for line in wfile:
  8. word = line[:-1]
  9. for i in range(len(word)):
  10. bucket = word[:i] + '_' + word[i+1:]
  11. if bucket in d:
  12. d[bucket].append(word)
  13. else:
  14. d[bucket] = [word]
  15. # add vertices and edges for words in the same bucket
  16. for bucket in d.keys():
  17. for word1 in d[bucket]:
  18. for word2 in d[bucket]:
  19. if word1 != word2:
  20. g.addEdge(word1,word2)
  21. return g

Listing 1

因为这是我们的第一个真实世界图问题,你可能想知道图是如何稀疏?这个问题的四个字母的单词列表是 5,110 字长。 如果我们使用邻接矩阵,则矩阵将具有5,110 * 5,110 = 26,112,100 个格。 由 buildGraph 函数构造的图正好有 53,286 个边,所以矩阵只有 0.20% 的单元格填充! 这是一个非常稀疏的矩阵。