插入和替换代价不均匀的Levenshtein距离:

Levenshtein distance with non uniform cost for insertions and substitutions:

本文关键字:Levenshtein 距离 不均匀 替换 代价 插入      更新时间:2023-10-16

我一直在尝试在c++中实现一个levelshtein距离函数,该函数根据要替换或插入的字符为替换和插入提供不同的权重。

成本是根据qwerty键盘上键的距离计算的。例如,在标准的编辑距离算法中,google、hoogle和zoogle之间的距离是相同的;1. 我想要的是它们的不同距离。比如google -> hoogle = 1, google -> zoogle = 4, hoogle -> zoogle = 5。

我遵循维基百科算法,使用矩阵进行记忆,并在c++中实现。下面是我的函数。

int levDist(string s, string t) {
    int i,j,m,n,temp,subsitutionCost, deletionCost, insertionCost, keyDist;
    deletionCost = 1;
    m = s.length();
    n = t.length();
    int d[m+1][n+1];
    for(i=0;i<=m;i++)
        d[i][0] = i;
    for(j=0;j<=n;j++)
        d[0][j] = j;
    for (j=1;j<=n;j++)
    {
        for(i=1;i<=m;i++)
        {
            // getKeyboardDist(char a, char b) gives distance b/w the two keys
            keyDist = getKeyboardDist(s[i-1],t[j-1]); 
            subsitutionCost = (s[i-1] == t[j-1]) ? 0 : keyDist;
            // this line is the one i think the problem lies in
            insertionCost = (i > j) ? getKeyboardDist(s[i-1],t[j-2]) : getKeyboardDist(s[i-2],t[j-1]);

            insertionCost = insertionCost ? insertionCost : 1;
            d[i][j] = min((d[i-1][j]   + deletionCost),
                      min((d[i][j-1]   + insertionCost),
                          (d[i-1][j-1] + subsitutionCost)));`
        }
    }
    return d[m][n];
}

现在替换工作正常,我相信,但问题是插入。我不知道如何找到哪些字符得到插入之间的距离。特别是当插入在字符串的开头或结尾时。

我将非常感谢任何帮助,如果还需要其他信息请告诉我。

您尝试做的事情对于替换是有意义的。你的假设是,一个人试图敲击X键时,敲击靠近X键的键比敲击远离X键的键更容易出错。

对于插入和删除没有太大意义,因为敲击一个额外的键(插入错误)或跳过一个键(删除错误)的行为与键的距离没有任何明显的关系。

你可能被这里"距离"的两种不同含义误导了。Levenshtein距离是在插入/替换/删除操作中测量字符串之间的距离。键盘距离是一种物理距离。这是用同一个词来描述的苹果和橙子。他们不太合得来。

您正在尝试确定Levenshtein操作的权重。键之间的物理距离为替换提供了合理的权重。

插入和删除的权值(每个只涉及一个字符)与物理分隔没有任何明显的关系。

你真正想要的是频率数据,关于人们实际上错误地插入和删除了哪些键。你会给最常见的相对较低的权重和最不常见的高权重。

@user6952491关于重复前一个键可能是高频插入错误的想法有其优点,但很难将其扩展到完整的加权方案。

如果你有猜测的心情,你可以假设在键盘的中间比在边缘更容易误插入一个键。假设fj的权重最低,而像~这样的字符被移动,在键盘的极端处权重很高,因为你不太可能不假思索地做出物理运动来键入它们。

我将把它留给你来形成一个类似的关于删除的猜测。

对于一般的打字,我猜测键盘错误与拼写错误的关系至少与物理错误的关系一样多。也就是说,人们会键入"receive",因为他们忘记了"i在e之前,c之后除外"的规则,而不是因为i相对于e的键盘位置。

其他类型的输入,例如计算机代码,可能有完全不同的错误模式。忘记的分号出现在脑海中!它们的权重很低!

因此,我几乎可以肯定,现代拼写检查器提供的建议根植于机器学习算法,它从过去成千上万人在类似任务中犯的错误中得出结论,而不是基于键盘距离的简单指标。

如果把所有键放在一个图中,就可以很容易地计算出它们的距离。如果您将其构建为简单的neighbor listmatrix,并使用您自己插入的值,则会更容易。

在我看来,插入应该被计算为左右(如果存在)字母之间的最小距离+ 1,因为Google和Google非常相似,但是Google和Google是非常远的。因此google->googl: =7。