Javascript Damerau-Levenshtein距离实现
我试图在JS中创建一个damerau-levenshtein距离函数 我在维基百科上找到了对该算法的描述,但它们并没有实现。它说: 设计一个合适的算法来计算无约束 Damerau–Levenshtein距离注意,始终存在一个最佳距离 编辑操作的序列,其中一旦转置的字母永远不会 后来修改过。因此,我们只需要考虑两种对称方式。 多次修改子字符串的方法:(1)转置字母和 在它们之间插入任意数量的字符,或(2)删除 相邻字符和转置字母的序列 删除后。这一想法的直接实现给出了 一种立方复杂度算法:O\left(M\cdot N\cdot\max(M,N) \右),其中M和N是字符串长度。利用 Lowrance和Wagner[7]这种幼稚的算法可以改进为 最坏情况下为O\左(M\cdot N\右)。有趣的是 可以修改bitap算法以处理转置。见 [1]中的信息检索部分提供了这种方法的示例 适应 第[1]节指出的问题对我来说更为复杂 如果我正确理解了这一点,那么用它创建一个实现就不那么容易了 以下是我目前使用的levenshtein实现:Javascript Damerau-Levenshtein距离实现,javascript,algorithm,ocr,levenshtein-distance,Javascript,Algorithm,Ocr,Levenshtein Distance,我试图在JS中创建一个damerau-levenshtein距离函数 我在维基百科上找到了对该算法的描述,但它们并没有实现。它说: 设计一个合适的算法来计算无约束 Damerau–Levenshtein距离注意,始终存在一个最佳距离 编辑操作的序列,其中一旦转置的字母永远不会 后来修改过。因此,我们只需要考虑两种对称方式。 多次修改子字符串的方法:(1)转置字母和 在它们之间插入任意数量的字符,或(2)删除 相邻字符和转置字母的序列 删除后。这一想法的直接实现给出了 一种立方复杂度算法:O\le
levenshtein=function (s1, s2) {
// discuss at: http://phpjs.org/functions/levenshtein/
// original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
// bugfixed by: Onno Marsman
// revised by: Andrea Giammarchi (http://webreflection.blogspot.com)
// reimplemented by: Brett Zamir (http://brett-zamir.me)
// reimplemented by: Alexander M Beedie
// example 1: levenshtein('Kevin van Zonneveld', 'Kevin van Sommeveld');
// returns 1: 3
if (s1 == s2) {
return 0;
}
var s1_len = s1.length;
var s2_len = s2.length;
if (s1_len === 0) {
return s2_len;
}
if (s2_len === 0) {
return s1_len;
}
// BEGIN STATIC
var split = false;
try {
split = !('0')[0];
} catch (e) {
// Earlier IE may not support access by string index
split = true;
}
// END STATIC
if (split) {
s1 = s1.split('');
s2 = s2.split('');
}
var v0 = new Array(s1_len + 1);
var v1 = new Array(s1_len + 1);
var s1_idx = 0,
s2_idx = 0,
cost = 0;
for (s1_idx = 0; s1_idx < s1_len + 1; s1_idx++) {
v0[s1_idx] = s1_idx;
}
var char_s1 = '',
char_s2 = '';
for (s2_idx = 1; s2_idx <= s2_len; s2_idx++) {
v1[0] = s2_idx;
char_s2 = s2[s2_idx - 1];
for (s1_idx = 0; s1_idx < s1_len; s1_idx++) {
char_s1 = s1[s1_idx];
cost = (char_s1 == char_s2) ? 0 : 1;
var m_min = v0[s1_idx + 1] + 1;
var b = v1[s1_idx] + 1;
var c = v0[s1_idx] + cost;
if (b < m_min) {
m_min = b;
}
if (c < m_min) {
m_min = c;
}
v1[s1_idx + 1] = m_min;
}
var v_tmp = v0;
v0 = v1;
v1 = v_tmp;
}
return v0[s1_len];
}
levenshtein=函数(s1,s2){
//讨论地点:http://phpjs.org/functions/levenshtein/
//原件:卡洛斯·R·L·罗德里格斯(http://www.jsfromhell.com)
//修正者:安诺马斯曼
//修订人:Andrea Giammarchi(http://webreflection.blogspot.com)
//重新实施人:Brett Zamir(http://brett-zamir.me)
//重新实施人:亚历山大M比迪
//例1:levenshtein('Kevin van Zonneveld','Kevin van Sommeveld');
//返回1:3
如果(s1==s2){
返回0;
}
变量s1_len=s1.length;
var s2_len=s2.length;
如果(s1_len==0){
返回s2_len;
}
如果(s2_len==0){
返回s1_len;
}
//开始静止
var分割=假;
试一试{
拆分=!('0')[0];
}捕获(e){
//早期IE可能不支持通过字符串索引进行访问
split=true;
}
//端静电
如果(拆分){
s1=s1.分割(“”);
s2=s2.分裂(“”);
}
var v0=新阵列(s1_len+1);
var v1=新阵列(s1_len+1);
变量s1_idx=0,
s2_idx=0,
成本=0;
对于(s1_idx=0;s1_idx
在Javascript中提供以下内容
可以更改权重器对象中操作的权重
var levenshteinWeighted= function(seq1,seq2)
{
var len1=seq1.length;
var len2=seq2.length;
var i, j;
var dist;
var ic, dc, rc;
var last, old, column;
var weighter={
insert:function(c) { return 1.; },
delete:function(c) { return 0.5; },
replace:function(c, d) { return 0.3; }
};
/* don't swap the sequences, or this is gonna be painful */
if (len1 == 0 || len2 == 0) {
dist = 0;
while (len1)
dist += weighter.delete(seq1[--len1]);
while (len2)
dist += weighter.insert(seq2[--len2]);
return dist;
}
column = []; // malloc((len2 + 1) * sizeof(double));
//if (!column) return -1;
column[0] = 0;
for (j = 1; j <= len2; ++j)
column[j] = column[j - 1] + weighter.insert(seq2[j - 1]);
for (i = 1; i <= len1; ++i) {
last = column[0]; /* m[i-1][0] */
column[0] += weighter.delete(seq1[i - 1]); /* m[i][0] */
for (j = 1; j <= len2; ++j) {
old = column[j];
if (seq1[i - 1] == seq2[j - 1]) {
column[j] = last; /* m[i-1][j-1] */
} else {
ic = column[j - 1] + weighter.insert(seq2[j - 1]); /* m[i][j-1] */
dc = column[j] + weighter.delete(seq1[i - 1]); /* m[i-1][j] */
rc = last + weighter.replace(seq1[i - 1], seq2[j - 1]); /* m[i-1][j-1] */
column[j] = ic < dc ? ic : (dc < rc ? dc : rc);
}
last = old;
}
}
dist = column[len2];
return dist;
}
var levenshteinWeighted=函数(序号1,序号2)
{
变量len1=seq1.1长度;
var len2=seq2.2长度;
varⅠ,j;
变异区;
var-ic,dc,rc;
var last,old,column;
变量加权器={
插入:函数(c){return 1.},
删除:函数(c){返回0.5;},
替换:函数(c,d){返回0.3;}
};
/*不要交换序列,否则会很痛苦的*/
if(len1==0 | | len2==0){
dist=0;
while(len1)
dist+=权重删除(seq1[--len1]);
while(len2)
dist+=权重插入(seq2[--len2]);
返回距离;
}
列=[];//malloc((len2+1)*sizeof(double));
//如果(!列)返回-1;
列[0]=0;
对于(j=1;j)你到底想做什么?你指的是(所谓的)Damerau-Levenshtein距离,但你的一段代码包含了经典的Levenshtein算法。如果你只需要换位支持,只需要更改几行代码。至于“无差异”在给定的字符之间,您必须为特定的编辑操作指定给定的惩罚。这可以处理表查找/插入,但在javascript中可能太慢,无法用于任何操作。是的,我的代码仅使用简单的Levenshtein算法。我有一个屏幕名称数据库(300个屏幕名称),还有一个OCR扫描仪,可以扫描一个屏幕名列表(300个屏幕名)。但是OCR扫描仪的结果不好。所以我想找到相似之处(这就是我目前在JS中所做的)。例如,“mikejew_e”被解释为“mikeiew e”。我现在正在使用levenshtein算法(最大距离为3),但它有点过于宽容。(距离为2,我有可能丢失一些匹配的屏幕名称)好的,我明白了。获得更好结果的基本步骤是为每个编辑操作指定特定的权重。将默认惩罚设置为1.0,并降低OCR程序可能误读的字符的惩罚。对于300个名称,这将足够快,即使是在javascript中。我刚刚发布了我的C实现要点:。这可能会给你一个想法我还记得github上有纯javascript实现,但是再也找不到链接了,抱歉!非常好,我会将其转换为JS。这正是我想要的