将一个单词转换为另一个单词的最短路径

dac*_*man 20 algorithm edit-distance shortest-path hamming-distance

对于Data Structures项目,我必须找到两个单词之间的最短路径(例如"cat""dog"),一次只能更改一个字母.我们给出了一个拼字游戏单词列表,用于查找我们的路径.例如:

cat -> bat -> bet -> bot -> bog -> dog
Run Code Online (Sandbox Code Playgroud)

我已经使用广度优先搜索解决了这个问题,但我正在寻找更好的东西(我用trie代表字典).

请给我一些更有效的方法(在速度和记忆方面)的想法.有些荒谬和/或挑战是首选.

我问过我的一个朋友(他是一名大三学生),他说这个问题没有有效的解决办法.他说我会学习为什么我参加算法课程.对此有何评论?

我们必须一个接一个地移动.我们不能去cat -> dat -> dag -> dog.我们还必须打印出遍历.

Jac*_*cob 15

新的答案

鉴于最近的更新,您可以尝试使用汉明距离作为启发式的A*.这是一个可接受的启发式算法,因为它不会高估距离

老答复

您可以修改用于计算Levenshtein距离的动态程序,以获得操作序列.

编辑:如果有一个恒定数量的字符串,问题可以在多项式时间内解决.另外,它是NP难的(维基百科都有)...假设你的朋友正在谈论NP难的问题.

编辑:如果您的琴弦长度相等,则可以使用汉明距离.

  • 鉴于应该是汉明距离的例子. (3认同)
  • 您不能修改Levenshtein函数来执行此操作,因为您有一个有限的有效单词字典 - 因此最短的有效路径可能比字符串中的字符数长得多. (2认同)

sdc*_*vvc 9

使用字典,BFS是最佳的,但所需的运行时间与其大小(V + E)成比例.对于n个字母,字典可能有〜a ^ n entires,其中a是字母大小.如果字典包含所有单词,但是应该在链的末尾,那么你将遍历所有可能的单词,但不会找到任何单词.这是图遍历,但大小可能呈指数级大.

您可能想知道是否可以更快地进行操作 - "智能地"浏览结构并在多项式时间内完成.我认为答案是否定的.

问题:

你有一个快速(线性)的方法来检查一个单词是否在字典中,两个单词u,v并且要检查是否有序列u - > a 1 - > a 2 - > ... - > a n - > v.

是NP难的.

证明:拿一些3SAT实例,比如

(p或q或不r)和(p或不q或r)

你将从0 000 00开始,并检查是否可以转到2 222 22.

第一个字符将是"我们完成了",三个接下来的位将控制p,q,r和两个接下来将控制子句.

允许的话是:

  • 任何以0开头且仅包含0和1的内容
  • 任何以2开头且合法的东西.这意味着它由0和1组成(除了第一个字符是2,所有子句位根据变量位正确设置,并且它们被设置为1(因此这表明公式是可满足的).
  • 任何以至少两个2开头的东西然后由0和1组成(正则表达式:222*(0 + 1)*,如22221101但不是2212001

要从0 000 00生成2 222 22,您必须以这种方式执行:

(1)翻转适当的位 - 例如,分成四个步骤的0 100 111.这需要找到3SAT解决方案.

(2)将第一位更改为2:2 100 111.在此您将验证这确实是一个3SAT解决方案.

(3)更改2 100 111 - > 2 200 111 - > 2 220 111 - > 2 222 111 - > 2 222 211 - > 2 222 221 - > 2 222 222.

这些规则强制您不能作弊(检查).只有当公式可以满足并且检查是NP难时,才可能进入2 222 22.我觉得它可能更难(可能是#P或FNP),但我认为NP硬度就足够了.

编辑:您可能对不相交的集数据结构感兴趣.这将使您可以从彼此访问的词典和组词.您还可以存储从每个顶点到根或某个其他顶点的路径.这将为您提供一条路径,而不是最短路径.