Javascript查找编辑距离未返回正确的值

时间:2015-11-23 03:47:37

标签: javascript recursion levenshtein-distance edit-distance

我正在研究一个计算两个字符串的编辑距离的函数,但根据这个计算器我得到的值不正确。我得到19并且计算器正在返回7.我不确定我的程序是否有错误我基于算法设计手册

var recFindEditDistance = function(P, T, i, j) {
    if (i === undefined || j === undefined) return recFindEditDistance(P, T, P.length - 1, T.length - 1);
    if (i === 0 && j === 0) return 0;
    if (i === 0) return j;
    if (j === 0) return i;

    var sub = recFindEditDistance(P, T, i-1, j-1) + (P[i]===T[j] ? 0 : 1);
    var del = recFindEditDistance(P, T, i, j-1) + 1;
    var add = recFindEditDistance(P, T, i-1, j) + 1;

    return Math.max(sub, add, del);
};

console.log(recFindEditDistance('ffadsfsadfasf', 'asdfasdf'));

2 个答案:

答案 0 :(得分:1)

每个位置的Levenshtein距离算法试图达到最小距离以到达下一个位置。

Wikipedia recurrence relation

与此同时,你正试图获得最大值:)

只需更改

return Math.max(sub, add, del);

return Math.min(sub, add, del);

它会起作用:)

<强>演示:

&#13;
&#13;
function recFindEditDistance(P, T, i, j) {
    if (i === undefined || j === undefined) return recFindEditDistance(P, T, P.length - 1, T.length - 1);
    if (i === 0 && j === 0) return 0;
    if (i === 0) return j;
    if (j === 0) return i;

    var sub = recFindEditDistance(P, T, i-1, j-1) + (P[i]===T[j] ? 0 : 1);
    var del = recFindEditDistance(P, T, i, j-1) + 1;
    var add = recFindEditDistance(P, T, i-1, j) + 1;

    return Math.min(sub, add, del);
};

document.body.innerText = recFindEditDistance('ffadsfsadfasf', 'asdfasdf');
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我完全意识到这个问题已经很久了,我之所以发布此问题只是因为它在我的Google搜索中被认可。即使Yeldar Kurmangaliyev接受的答案正确回答了眼前的问题,但必须指出,上述解决方案仍然存在至少两个缺陷:

  1. 它无法正确处理所有情况-仅对第一个符号不同的字符串无效:例如它会错误地为字符串canpan返回距离0。要解决此问题,我们可以执行以下操作:
function recFindEditDistance(P, T, i, j) {
    if (i === undefined || j === undefined) return recFindEditDistance(P, T, P.length - 1, T.length - 1);
    if (i === 0 && j === 0) return (P.charAt(i) === T.charAt(j)) ? 0 : 1;
    if (i === 0) return j;
    if (j === 0) return i;
    var sub = recFindEditDistance(P, T, i-1, j-1) + (P[i]===T[j] ? 0 : 1);
    var del = recFindEditDistance(P, T, i, j-1) + 1;
    var add = recFindEditDistance(P, T, i-1, j) + 1;
    return Math.min(sub, add, del);
};

console.log(recFindEditDistance('can', 'can'));
  1. 效率不高,因为递归将多次处理许多相同的子问题,例如:我们可能多次解决recFindEditDistance(P, T, 3, 2)。因为结果是确定性的,所以我们不需要这样做,并且一旦找到特定子问题的解决方案,就无需再次计算。由于找到Levenstein距离是一个动态规划问题,因此,我们可以使用诸如memoizatation or tabulation之类的技术来解决这一问题。有关使用列表的完整解决方案,请参见here