查找两个单词之间相邻单词的列表

时间:2013-04-19 02:59:44

标签: ruby algorithm data-structures

我正在努力解决实践中的编程挑战,并且无法找到用于实现解决方案的良好数据结构/算法。

背景

如果您可以通过添加,删除或更改单个字母将一个单词更改为另一个单词,请将两个单词称为“邻近”。

“单词列表”是连续单词相邻的唯一单词的有序列表。

问题:

编写一个程序,它将两个单词作为输入并遍历字典并在它们之间创建一个单词列表。

示例:

hate  → love:     hate, have, hove, love
dogs  → wolves:   dogs, does, doles, soles, solves, wolves
man   → woman:    man, ran, roan, roman, woman
flour → flower:   flour, lour, dour, doer, dower, lower, flower

我不太确定如何处理这个问题,我的第一次尝试涉及创建第一个单词的排列,然后尝试替换它中的字母。我的第二个想法可能是suffix tree

任何想要或至少打破问题的想法都会受到赞赏。请记住,这不是家庭作业,而是我自己编写的编程挑战。

5 个答案:

答案 0 :(得分:4)

这个谜题首先由查尔斯·道奇森(Charles Dodgson)陈述,他用笔名刘易斯卡罗尔(Lewis Carroll)写下了爱丽丝梦游仙境奇迹。

基本思想是创建一个图形结构,其中节点是字典中的单词,边缘连接相隔一个字母的单词,然后从第一个单词开始,通过图形进行广度优先搜索,直到你找到了第二个字。

我讨论了这个问题,并提供了一个实现,其中包含一个聪明的算法,用于在my blog标识“邻近”单词。

答案 1 :(得分:3)

我不知道这是否是您正在寻找的解决方案类型,但是一个活跃的研究领域是构建“编辑距离1”词典,以快速查找相邻的单词(使用您的说法)搜索术语建议,数据输入校正和生物信息学(例如在染色体中发现相似性)。请参阅示例this research paper。如果没有索引整个字典,至少可能会建议您使用搜索启发式。

答案 2 :(得分:3)

我自己做了这个并用它来创建一个(不是很好的)Windows游戏。

我使用其他人推荐的方法将其实现为图形,其中每个节点都是一个单词,如果它们在一个字母中不同,则它们是相连的。这意味着您可以使用众所周知的图论结果来查找单词之间的路径(例如,简单的递归,其中知道距离1处的单词允许您在距离2处找到单词)。

棘手的部分是建立图表。坏消息是它是O(n ^ 2)。好消息是它不必实时完成 - 而不是您的程序从文件中读取字典单词,而是读入您之前烘焙的数据结构。

关键的洞察力是订单无关紧要,事实上它会妨碍。您需要构建另一种形式来保存删除订单信息的单词,并允许更容易地比较单词。你可以在O(n)中做到这一点。你有很多选择;我将展示两个。

  1. 对于单词拼图我退出时经常使用我称之为字母词典的编码。一个单词由另一个单词表示,该单词具有相同的字母但按字母顺序排列。所以“汽车”变成了“车”。列表和切口都变成“最”。这是一个比原始单词更好的比较结构,但存在更好的比较(但是,对于其他单词谜题,它是一个非常有用的结构)。

  2. 字母数。一个包含26个值的数组,显示单词中该字母的频率。因此,对于“汽车”,它开始1,0,1,0,0 ...因为有一个“a”和一个“c”。保留非零条目的外部列表(单词中出现的字母),因此您只需要检查5或6个值而不是26个。通过确保最多两个来快速比较此表单中保存的两个单词非常简单计数是不同的。这是我要使用的那个。

  3. 所以,这就是我做到的。

    我编写了一个实现上述数据结构的程序。

    它有一个名为WordNode的类。这包含原始单词;一个字母不同的所有其他WordNode的列表;一个由26个整数组成的数组,给出每个字母的频率,字母计数数组中的非零值列表。

    初始化器填充字母频率数组和相应的非零值列表。它将连接的WordNode列表设置为零。

    在为每个单词创建WordNode类的实例后,我运行了一个比较方法,该方法检查频率计数是否在不超过两个位置不同。通常比单词中的字母略少一些;还不错。如果它们在两个地方不同,则它们相差一个字母,并且我将WordNode添加到只有一个字母的WordNode列表中。

    这意味着我们现在有一个字母不同的所有单词的图表。

    您可以导出整个数据结构或删除字母频率和其他不需要的东西并保存(我使用序列化的XML。如果你这样做,请确保检查它处理WordNodes列表作为参考而不是嵌入对象)。

    你的实际游戏只需要阅读这个数据结构(而不​​是字典),它可以找到一个字母与直接查找不同的单词,基本上是零时间。

    可惜我的游戏很糟糕。

答案 3 :(得分:1)

我能想到的最简单(递归)算法(好吧,我能想到的唯一一个)是

  • 初始化空黑名单
  • 从词典中取出所有单词,这是当前单词的有效步骤
  • 删除黑名单中的内容
  • 检查您是否可以找到目标字词。
    • 如果没有,请对您在上一步中找到的所有单词重复算法
    • 如果是的话,你找到了。返回递归打印您找到的路径中的所有单词。

也许有更多时间的人可以为此添加ruby代码?

答案 4 :(得分:0)

试试这个

x = 'hate'
puts x = x.next until x == 'love'

如果你将它与字典查找相结合,你将获得该字典中所有有效单词的列表。