我正在尝试改进现有的javascript levenstein距离计算源代码,以生成不仅包含当前setps值的martix,还包括所采取的操作(插入,替换,删除或匹配)
我在“动作”矩阵中得到了错误的结果:
在我们看到的算法中(不是来自维基百科的js):
d[i, j] := minimum
(
d[i-1, j] + 1, // a deletion
d[i, j-1] + 1, // an insertion
d[i-1, j-1] + 1 // a substitution
)
因此,在我的JS代码中,我执行以下操作:
// Step 6
d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
// a deletion
if(d[i][j] == d[i - 1][j] + 1) {
actions[i][j] = 'D';
}
// a insertion
if(d[i][j] == d[i][j - 1] + 1) {
actions[i][j] = 'I';
}
// a substitution
if(d[i][j] == d[i - 1][j - 1] + cost) {
actions[i][j] = 'R';
}
d
矩阵(二维数组)用于值,并且使用正确的值填充。
但为什么相应的actions
矩阵不显示逻辑算法会做什么?
在分配'我','R','D'方面我做错了什么?或者它是正确的,对我来说似乎不合逻辑,因为我认为在上述场景中,插入将在第二步中发生。
BTW,在Levenstein算法的情况下生成这样的“动作”矩阵实际上是否明智?答案 0 :(得分:1)
通常有很多方法可以为任何给定的Levensthein矩阵生成一组“动作”。在您的示例中,您可以将结果成本矩阵追溯到最小值,您将找到相当多的路径。
以下是一些例子:
(0,0)(0,1)(1,2)(1,3)(2,4)(3,5)
(0,0)(1,1)(1,2)(1,3)(2,4)(3,5)
(0,0)(0,1)(0,2)(1,3)(2,4)(3,5)
所以我可以找到相同距离矩阵的至少三种不同的解释。这意味着,除非您有某种方式来偏向方向(例如,优先选择替换而不是插入的删除),否则您的矩阵将非常模糊。
现在你建议用于填充动作矩阵的算法:在你的情况下,你隐含地喜欢替换(因为它们被最后检查并将覆盖先前的选择)而不是删除的插入和插入。这就是矩阵中所有R
的来源。让我们看看这里发生了什么:
当我们更喜欢替换时,建议的解决方案是在其他任何内容之前插入A
和N
,然后将M
替换为N
,将A
替换为{{1} {}}和A
X
。如果你检查你可以看到这将花费四(两次插入和两次“实际”替换),这正是矩阵确定的(这是我追踪的路径中的最后一条路径)。
现在再次检查您的操作矩阵,我们发现,如果我们从最后一个角落追溯:S
,R
和R
位于R
,{ {1}}和(3,5)
。这相当于(2,4)
到(1,3)
的最终替换。然而,这里缺少的是插入我在上面描述的前导MAX
。查看矩阵,可以看到第一行和列中有数字,而不是动作。然而,这些应该分别是删除和替换,在这种情况下,您可以生成最终序列NAS
,其成本为4,将AN
转换为SSRRR
。
但是你应该知道,没有必要像你一样计算矩阵中的动作,因为所有信息都可以在最终的成本矩阵中获得。您始终可以追溯从最后一个角落到第一个角落的最终成本矩阵,您将能够重建所有可以将一个单词转换为另一个单词的路径。但是,一旦你在动作矩阵中修复了动作,所有可能性中只剩下一条路径。
这必须做很多事情,成本很好且唯一地定义,而路径可能非常模糊。
修改的
以下是路径的完整动作矩阵,其中包含歧义:
MAX