gpt4 book ai didi

javascript - 如何优化 levenshtein 距离以检查距离为 1?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:41:36 24 4
gpt4 key购买 nike

我正在开发一款游戏,我只需要检查两个单词之间的距离是否为 0 或 1,如果是,则返回 true。我找到了一个通用的编辑距离算法:

function levenshtein(s, t) {
if (s === t) { return 0; }
var n = s.length, m = t.length;
if (n === 0 || m === 0) { return n + m; }
var x = 0, y, a, b, c, d, g, h, k;
var p = new Array(n);
for (y = 0; y < n;) { p[y] = ++y; }
for (;
(x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x; b = x + 1; d = x + 2; g = x + 3; h = x + 4;

for (y = 0; y < n; y++) {
k = s.charCodeAt(y);
a = p[y];

if (a < c || b < c) { c = (a > b ? b + 1 : a + 1); }
else { if (e1 !== k) { c++; } }

if (c < b || d < b) { b = (c > d ? d + 1 : c + 1); }
else { if (e2 !== k) { b++; } }

if (b < d || g < d) { d = (b > g ? g + 1 : b + 1); }
else { if (e3 !== k) { d++; } }

if (d < g || h < g) { g = (d > h ? h + 1 : d + 1); }
else { if (e4 !== k) { g++; } }

p[y] = h = g; g = d; d = b; b = c; c = a;
}
}

for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) { d = (a > d ? d + 1 : a + 1); }
else {
if (e !== s.charCodeAt(y)) { d = c + 1; }
else { d = c; }
}
p[y] = d;
c = a;
}
h = d;
}

return h;
}

这行得通,但这个点将成为一个热点,每秒可能运行数十万次,我想优化它,因为我不需要通用算法,只需要一个检查是否有距离为 0 或 1。

我尝试编写它并想出了这个:

function closeGuess(guess, word) {
if (Math.abs(word.length - guess.length) > 1) { return false; }

var errors = 0, guessIndex = 0, wordIndex = 0;

while (guessIndex < guess.length || wordIndex < word.length) {
if (errors > 1) { return false; }
if (guess[guessIndex] !== word[wordIndex]) {
if (guess.length < word.length) { wordIndex++; }
else { guessIndex++; }
errors++;
} else {
wordIndex++;
guessIndex++;
}
}

return true;
}

但是在分析之后我发现我的代码慢了一倍,这让我很惊讶,因为我认为通用算法是 O(n*m) 而我认为我的是 O(n)。

我一直在测试这个 fiddle 的性能差异:https://jsfiddle.net/aubtze2L/3/

有没有更好的算法可以使用,或者有什么方法可以优化我的代码以使其更快?

最佳答案

我没有看到比旧的 for 循环更快的更优雅的方法:

function lev01(a, b) {
let la = a.length;
let lb = b.length;
let d = 0;
switch (la - lb) {
case 0: // mutation
for (let i = 0; i < la; ++i) {
if (a.charAt(i) != b.charAt(i) && ++d > 1) {
return false;
}
}
return true;
case -1: // insertion
for (let i = 0; i < la + d; ++i) {
if (a.charAt(i - d) != b.charAt(i) && ++d > 1) {
return false;
}
}
return true;
case +1: // deletion
for (let i = 0; i < lb + d; ++i) {
if (a.charAt(i) != b.charAt(i - d) && ++d > 1) {
return false;
}
}
return true;
}
return false;
}

console.log(lev01("abc", "abc"));
console.log(lev01("abc", "abd"));
console.log(lev01("abc", "ab"));
console.log(lev01("abc", "abcd"));
console.log(lev01("abc", "cba"));

性能比较(Chrome):

  • 80.33ms - lev01(这个答案)
  • 234.84ms - lev
  • 708.12 毫秒 - 关闭

关于javascript - 如何优化 levenshtein 距离以检查距离为 1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37904182/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com