使用Levenshtein距离匹配的匹配百分比

时间:2012-05-01 22:46:09

标签: distance percentage ranking levenshtein-distance

我正在尝试使用Levenshtein距离算法将单个搜索词与可能匹配的词典进行匹配。该算法返回一个距离,表示为将搜索字符串转换为匹配字符串所需的操作数。 我想在排名最高的“N”(比方说10)比赛的百分比列表中显示结果。

由于搜索字符串可以比单个字典字符串更长或更短,因此将距离表示为百分比的适当逻辑是什么,这将定性地反映出查询字符串的每个结果的“百分比”接近程度,100%表示完全匹配。

我考虑了以下选项:

Q = query string
M = matched string
PM = Percentage Match
Option 1. PMi = (1 - Lev_distance(Q, Mi)/Strlen(Q)) * 100
Option 2. PMi = (1 - Lev_distance(Q, Mi)/max(Strlen(Q), strlen(Mi))) * 100

如果距离大于搜索字符串长度(匹配字符串为long),则选项1可能为负百分比。例如查询“ABC”与“ABC Corp.”匹配会导致负匹配百分比。

选项2似乎没有在一组Mi中给出一致的百分比,因为每个计算可能使用不同的分母,因此得到的百分比值不会被标准化。

我能想到的另一种方法是放弃lev_distance与字符串长度的比较,而是将顶部“N”匹配的比较距离显示为反百分位数等级(100百分位等级)。 / p>

有什么想法?有更好的方法吗?我必须遗漏一些东西,因为Levenshtein距离可能是最常见的模糊匹配算法,这一定是一个非常常见的问题。

8 个答案:

答案 0 :(得分:32)

我遇到了类似的问题,这个帖子帮助我找到了解决方案。希望它也可以帮助别人。

int levDis = Lev_distance(Q, Mi)
int bigger = max(strlen(Q), strlen(Mi))
double pct = (bigger - levDis) / bigger

如果两个字符串完全相同则应返回100%,如果两个字符串完全不同则返回0%。

(对不起,如果我的英语不太好)

答案 1 :(得分:5)

我解决这个问题的方法是计算最大允许操作,这是Levenshtein距离。我使用的公式是:

percent = 0.75; // at least 75% of string must match
maxOperationsFirst = s1.length() - s1.length() * percent;
maxOperationsSecond = s2.length() - s2.length() * percent;
maxOperations = round(min(maxOperationsFirst, maxOperationsSecond));

它计算每个字符串的最大操作数,我相信计算很容易理解。我使用两个结果的最小值并将其四舍五入到最接近的整数。您可以跳过此部分并仅使用任一字符串中的max操作值,这实际上取决于您的数据。

一旦获得了最大操作次数,就可以将其与levenshtein结果进行比较,并确定该字符串是否可接受。这样你可以使用任何扩展的levenshtein方法,例如Damerau–Levenshtein distance,它计算拼写错误,例如。测试 - > tset ,仅作为1个操作,这在检查那些经常发生拼写错误的用户输入时非常有用。

我希望这有助于您了解如何解决此问题。

答案 2 :(得分:0)

(1 - (levNum / Math.max(s.length,t.length) ) ) *100

应该是正确的

答案 3 :(得分:0)

这基本上是我在问题中提到的选项2。但是,让我演示一下这种方法的问题。

Q = "ABC Corp" (len = 8)
M1 = "ABC"
M2 = "ABC Corporati"
M3 = "ABC Corp"

我选择了M1和M2,使得它们的Lev距离相同(每个5个)。使用选项2,匹配百分比为

M1 = (1 - 5/8)*100  = 37.5%
M2 = (1 - 5/13)*100 = 61.5%
M3 = 100%

正如您所看到的那样,如果我按顺序呈现匹配,M1和M2之间存在巨大的等级差异,即使它们具有完全相同的lev距离。你看到了问题吗?

答案 4 :(得分:0)

这个怎么样:

100 - ( ((2*Lev_distance(Q, Mi)) / (Q.length + Mi.length)) * 100 )

它在(Q, M1)(Q,M2)

上提供相同的距离

答案 5 :(得分:0)

levenshtein距离的最大数量为const centerPosition = window.innerWidth / 2; const coords = `m${centerPosition},0 v50 a30,30 0 0 1 -30,30 h-480 a30,30 0 0 0 -30,30 v120`; return coords; 。我认为是真的。但是我们不应该除以它。

[l1, l2].max

Levenshtein看起来不是比较以百分比表示的字符串的可靠方法。我不想将相似的字符串视为 100%不同

我建议仅分析每个序列与LCS之间的差异。

gem install levenshtein diff-lcs

Diff::LCS.lcs "abc", "qwer"
=> []
Levenshtein.distance("abc", "qwer").to_f / [3, 4].max
=> 1.0

Diff::LCS.lcs "abc", "cdef"
=> ["c"]
Levenshtein.distance("abc", "cdef").to_f / [3, 4].max
=> 1.0

Diff::LCS.lcs "1234", "34567890"
=> ["3", "4"]
Levenshtein.distance("1234", "34567890").to_f / [4, 8].max
=> 1.0

答案 6 :(得分:0)

Max = Lev_distance(Q,''); //max operations to transform query string to empty string
PM = (Max - Lev_distance(Q, Mi)) / Max * 100%;

我认为这足以满足您的需求。它对极值是正确的(完全满足相同和完全不同的字符串)并且合理

答案 7 :(得分:0)

我认为更简单的方法可能是:

from nltk import edit_distance

str1 = 'abc'
str2 = 'abd'
edit_dist  = edit_distance(str1,str2)
len_total = len(str1)+len(str2)
pct_edit_dist = ((len_total-edit_dist)/len_total)*100
print(pct_edit_dist)

pct_edit_dist 为 100 表示完全匹配,0 表示不匹配。