Jaro-Winkler Distance 算法
这是一种计算两个字符串之间相似度的方法,想必都听过Edit Distance,Jaro-inkler Distance 是Jaro Distance的一个扩展,而Jaro Distance(Jaro 1989;1995)据说是用来判定健康记录上两个名字是否相同,也有说是是用于人口普查,具体干什么就不管了,让我们先来看一下Jaro Distance的定义。
两个给定字符串S1和S2的Jaro Distance为:
m是匹配的字符数;
t是换位的数目。
两个分别来自S1和S2的字符如果相距不超过 时,我们就认为这两个字符串是匹配的;而这些相互匹配的字符则决定了换位的数目t,简单来说就是不同顺序的匹配字符的数目的一半即为换位的数目t,举例来说,MARTHA与MARHTA的字符都是匹配的,但是这些匹配的字符中,T和H要换位才能把MARTHA变为MARHTA,那么T和H就是不同的顺序的匹配字符,t=2/2=1.
那么这两个字符串的Jaro Distance即为:
而Jaro-Winkler则给予了起始部分就相同的字符串更高的分数,他定义了一个前缀p,给予两个字符串,如果前缀部分有长度为 的部分相同,则Jaro-Winkler Distance为:
dj是两个字符串的Jaro Distance
是前缀的相同的长度,但是规定最大为4
p则是调整分数的常数,规定不能超过0.25,不然可能出现dw大于1的情况,Winkler将这个常数定义为0.1
这样,上面提及的MARTHA和MARHTA的Jaro-Winkler Distance为:
dw = 0.944 + (3 * 0.1(1 − 0.944)) = 0.961
以上资料来源于维基百科:
http://en.wikipedia.org/wiki/Jaro-Winkler_distance
lucene中实现代码分析:
public class JaroWinklerDistance implements StringDistance { private float threshold = 0.7f; private int[] matches(String s1, String s2) { String max, min; if (s1.length() > s2.length()) { max = s1; min = s2; } else { max = s2; min = s1; } // 两个分别来自s1和s2的字符如果相距不超过 floor(max(|s1|,|s2|) / 2) -1, 我们就认为这两个字符串是匹配的, 因此,查找时, // 超过此距离则停止 int range = Math.max(max.length() / 2 - 1, 0); // 短的字符串, 与长字符串匹配的索引位 int[] matchIndexes = new int[min.length()]; Arrays.fill(matchIndexes, -1); // 长字符串匹配的标记 boolean[] matchFlags = new boolean[max.length()]; // 匹配的数目 int matches = 0; // 外层循环,字符串最短的开始 for (int mi = 0; mi < min.length(); mi++) { char c1 = min.charAt(mi); // 可能匹配的距离,包括从给定位置从前查找和从后查找 for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max .length()); xi < xn; xi++) { // 排除被匹配过的字符,若找到匹配的字符,则停止 if (!matchFlags[xi] && c1 == max.charAt(xi)) { matchIndexes[mi] = xi; matchFlags[xi] = true; matches++; break; } } } // 记录min字符串里匹配的字符串,保持顺序 char[] ms1 = new char[matches]; // 记录max字符串里匹配的字符串,保持顺序 char[] ms2 = new char[matches]; for (int i = 0, si = 0; i < min.length(); i++) { if (matchIndexes[i] != -1) { ms1[si] = min.charAt(i); si++; } } for (int i = 0, si = 0; i < max.length(); i++) { if (matchFlags[i]) { ms2[si] = max.charAt(i); si++; } } // 查找换位的数目 int transpositions = 0; for (int mi = 0; mi < ms1.length; mi++) { if (ms1[mi] != ms2[mi]) { transpositions++; } } // 查找相同前缀的数目 int prefix = 0; for (int mi = 0; mi < min.length(); mi++) { if (s1.charAt(mi) == s2.charAt(mi)) { prefix++; } else { break; } } // 返回匹配数目(m),换位的数目(t),相同的前缀的数目,字符串最长 return new int[] { matches, transpositions / 2, prefix, max.length() }; } public float getDistance(String s1, String s2) { int[] mtp = matches(s1, s2); // 返回匹配数目(m) float m = (float) mtp[0]; if (m == 0) { return 0f; } // Jaro Distance float j = ((m / s1.length() + m / s2.length() + (m - mtp[1]) / m)) / 3; // 计算Jaro-Winkler Distance, 这里调整分数的因数=Math.min(0.1f, 1f / mtp[3]) float jw = j < getThreshold() ? j : j + Math.min(0.1f, 1f / mtp[3]) * mtp[2] * (1 - j); return jw; } /** * Sets the threshold used to determine when Winkler bonus should be used. * Set to a negative value to get the Jaro distance. * @param threshold the new value of the threshold */ public void setThreshold(float threshold) { this.threshold = threshold; } /** * Returns the current value of the threshold used for adding the Winkler bonus. * The default value is 0.7. * @return the current value of the threshold */ public float getThreshold() { return threshold; } }
相关推荐
C和Ruby实现都支持任何类型的字符串编码,例如UTF-8,EUC-JP,Big5等。安装gem install jaro_winkler用法require 'jaro_winkler'# Jaro Winkler DistanceJaroWinkler . distance "MARTHA" , "MARHTA"# => 0.9611...
当前实现了十二种算法(包括Levenshtein编辑距离和同级,Jaro-Winkler,最长公共子序列,余弦相似性等)。 查看下面的摘要表以获取完整列表... 下载 使用Maven: <groupId>info.debatty <artifactId>java-...
当前实现了十二种算法(包括Levenshtein编辑距离和同级,Jaro-Winkler,最长公共子序列,余弦相似性等)。 查看下面的摘要表以获取完整列表...下载使用NuGet: Install-Package F23.StringSimilarity总览下面介绍了...
Strutil strutil提供了用于计算字符串相似度的字符串度量标准以及其他字符串实用程序功能。 完整文档可在以下找到: : 。安装 go get github.com/adrg/strutil字符串指标杰罗·温克勒史密斯·沃特曼·高图索伦森-...
贝达 获取BEDA ...介绍 BEDA是一个golang库,用于检测两个单词或...Jaro&Jaro Winkler Distance:一个字符串度量,用于测量两个序列之间的编辑距离。 BEDA是印度尼西亚语中“不同”的意思。 用法 import "github.com/h
Spark的字符串相似性函数和语音算法。 见如果你使用PySpark。 项目设置 更新您的build.sbt文件以导入库。 libraryDependencies += "org.apache.commons" % "commons-text" % "1.1" // Spark 3 ...
当前实现了十二种算法(包括Levenshtein编辑距离和同级,Jaro-Winkler,最长公共子序列,余弦相似性等)。 查看下面的摘要表以获取完整列表... 下载 从pypi: # pip install strsim # deprecated, do not use this...
Jellyfish是一个Python库,用于对字符串进行近似和语音匹配。 由James Turk < >和Michael Stephens撰写。 有关贡献者,请参见 。 有关文档,请参见 。 来源可从。 水母> = 0.7仅支持Python 3,如果您需要...
包度量标准提供了许多算法来计算字符串之间的距离。 有一些实现可以计算流行的Levenshtein距离(又称“编辑距离”或Wagner-Fischer)以及Jaro距离,Jaro-Winkler距离等。如何汇入import "github....
尽管所有算法都可以公开使用并且可以提供其原始结果,但是它们已经方便地组合在一起,可以选择性地使用它们来判断两个字符串的近似相等性。 这可以通过IsSimilar扩展并通过设置所需的StringComparisonOptions和...