`
jimmee
  • 浏览: 540265 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

字符串相似算法-(1) Jaro-Winkler Distance

阅读更多

Jaro-Winkler Distance 算法

 

这是一种计算两个字符串之间相似度的方法,想必都听过Edit Distance,Jaro-inkler Distance Jaro Distance的一个扩展,而Jaro DistanceJaro 1989;1995)据说是用来判定健康记录上两个名字是否相同,也有说是是用于人口普查,具体干什么就不管了,让我们先来看一下Jaro Distance的定义。

 

两个给定字符串S1S2Jaro Distance为:

 

 

 

m是匹配的字符数;

t是换位的数目。

 

      两个分别来自S1S2的字符如果相距不超过 时,我们就认为这两个字符串是匹配的;而这些相互匹配的字符则决定了换位的数目t,简单来说就是不同顺序的匹配字符的数目的一半即为换位的数目t,举例来说,MARTHAMARHTA的字符都是匹配的,但是这些匹配的字符中,TH要换位才能把MARTHA变为MARHTA,那么TH就是不同的顺序的匹配字符,t=2/2=1.

 

     那么这两个字符串的Jaro Distance即为:

 

 

     而Jaro-Winkler则给予了起始部分就相同的字符串更高的分数,他定义了一个前缀p,给予两个字符串,如果前缀部分有长度为 的部分相同,则Jaro-Winkler Distance为:

 

 

dj是两个字符串的Jaro Distance

是前缀的相同的长度,但是规定最大为4

p则是调整分数的常数,规定不能超过0.25,不然可能出现dw大于1的情况,Winkler将这个常数定义为0.1

这样,上面提及的MARTHAMARHTAJaro-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;
  }
}

 

  • 大小: 2.1 KB
  • 大小: 1.6 KB
  • 大小: 2.2 KB
  • 大小: 1.2 KB
分享到:
评论

相关推荐

    匹配算法Jaro–Winkler_distance简介1

    Jaro-Winkler Distance是一种衡量两个字符串相似度的算法,主要应用于数据清洗、去重以及记录链接等领域。这个算法由Martin Winkler在1990年提出,是对原始Jaro距离的改进,尤其适用于姓名等较短字符串的相似度计算...

    Jaro–Winkler distance算法

    Jaro–Winkler distance算法是一种计算两个字符串之间相似度的算法,主要用于record linkage/数据连接(duplicate detection/重复记录)方面的领域。该算法是Jaro distance算法的变种,适合于串比如名字这样较短的...

    Java字符串相似度:各种字符串相似度和距离算法的实现:Levenshtein,Jaro-winkler,n-Gram,Q-Gram,Jaccard索引,最长公共子序列编辑距离,余弦相似度..

    当前实现了十二种算法(包括Levenshtein编辑距离和同级,Jaro-Winkler,最长公共子序列,余弦相似性等)。 查看下面的摘要表以获取完整列表... 下载 使用Maven: &lt;groupId&gt;info.debatty &lt;artifactId&gt;java-...

    字符串相似度算法

    5. **Jaro-Winkler距离**:Jaro距离关注字符的匹配和顺序,Winkler后来对其进行改进,增加了前几个字符相同时的加权项,对于人名和地址等短字符串的相似度计算特别有效。 6. **Smith-Waterman算法**:在生物信息学...

    jaro_winkler:Jaro-Winkler距离算法的Ruby&C实现,支持UTF-8字符串

    C和Ruby实现都支持任何类型的字符串编码,例如UTF-8,EUC-JP,Big5等。安装gem install jaro_winkler用法require 'jaro_winkler'# Jaro Winkler DistanceJaroWinkler . distance "MARTHA" , "MARHTA"# =&gt; 0.9611...

    字符串相似度比较T-2021-7-1.rar

    本资料“字符串相似度比较T-2021-7-1.rar”显然聚焦于探讨如何衡量两个字符串之间的相似程度,以及在特定情境下,如站名对比,如何应用这些方法。 字符串相似度比较的目标是量化两个字符串之间的相似性,这通常通过...

    Oracle字符相似度函数

    - **JARO_WINKLER()**:此函数基于Jaro距离算法,并加入了Winkler的改进,特别适用于短字符串的相似度计算。它考虑了字符的匹配、交换和插入操作,同时对字符串开头的相似部分给予额外的分数。返回值同样在0到1之间...

    sim.rar_mycbr_python 相似性_字符串相似性

    6. **Jaro-Winkler 距离**:特别适用于名字和地址等短字符串的相似性比较,重视前几个字符的匹配。 在实际应用中,选择哪种方法取决于具体的需求。例如,如果我们要识别用户输入错误的关键词,Levenshtein距离可能...

    使用最短编辑距离算法判断两个字符串的相似度

    此外,还有其他字符串相似度度量,如Jaccard相似度、Jaro-Winkler距离、余弦相似度等,它们在不同的应用场景下各有优势。 总之,最短编辑距离算法是计算字符串相似度的一种基础且重要的方法,它在文本处理领域有着...

    比较字符串是否相似.rar

    9. **Jaro-Winkler距离**:这是一种改进的字符串相似度算法,特别适合名字和地址的匹配,它考虑到字符顺序和接近度。 在实际应用中,选择哪种方法取决于具体需求,比如速度、精度、资源消耗等因素。例如,对于用户...

    字符串相似度比较

    4. **Jaro-Winkler距离**:特别适合名字和地址等短字符串的比较,考虑了字符的顺序和位置。 5. **Hamming距离**:只有当两个字符串长度相同时才适用,计算对应位置字符不同的个数。 6. **编辑距离(Edit Distance ...

    LD的两字符串相似度计算.zip

    3. **其他相似度度量**:除了Levenshtein Distance,还有Jaccard相似度、余弦相似度、Jaro-Winkler距离等其他字符串相似度计算方法,它们在不同的场景下各有优势。 4. **汉明距离**:如果只考虑替换操作,不涉及插入...

    文本指标:在Haskell中有效地计算各种字符串指标

    在这个主题中,我们将深入探讨如何在Haskell这种纯函数式编程语言中高效地实现几种常见的字符串指标:Levenshtein距离、Jaccard相似性、Jaro-Winkler距离、Hamming距离以及Jaro距离。 首先,让我们从Levenshtein...

    StringSimilarity.NET:Java字符串相似性的.NET端口

    当前实现了十二种算法(包括Levenshtein编辑距离和同级,Jaro-Winkler,最长公共子序列,余弦相似性等)。 查看下面的摘要表以获取完整列表...下载使用NuGet: Install-Package F23.StringSimilarity总览下面介绍了...

    strutil:Golang度量标准,用于计算字符串相似度和其他字符串实用程序功能

    Strutil strutil提供了用于计算字符串相似度的字符串度量标准以及其他字符串实用程序功能。 完整文档可在以下找到: : 。安装 go get github.com/adrg/strutil字符串指标杰罗·温克勒史密斯·沃特曼·高图索伦森-...

    edits.cr:编辑距离算法公司。 Jaro,Damerau-Levenshtein和最佳对准

    1. **Jaro距离**:由Martin Winkler在1980年代提出的Jaro距离是一种衡量两个字符串相似度的度量。它考虑了匹配字符的数量、字符的相对位置和短串的转移。Jaro-Winkler距离是Jaro距离的一个改进版本,尤其适用于名字...

    编辑距离源码与程序

    编辑距离(Edit Distance)是一种衡量两个字符串相似度的算法,广泛应用于文本处理、搜索引擎优化、生物信息学等领域。它的核心思想是通过插入、删除、替换等操作将一个字符串转换成另一个字符串所需的最小步骤数。...

    beda:Beda是一个golang库,用于检测两个字符串的相似程度

    贝达 获取BEDA ...介绍 BEDA是一个golang库,用于检测两个单词或...Jaro&Jaro Winkler Distance:一个字符串度量,用于测量两个序列之间的编辑距离。 BEDA是印度尼西亚语中“不同”的意思。 用法 import "github.com/h

    spark-stringmetric:Spark函数运行流行的语音和字符串匹配算法

    Spark的字符串相似性函数和语音算法。 见如果你使用PySpark。 项目设置 更新您的build.sbt文件以导入库。 libraryDependencies += "org.apache.commons" % "commons-text" % "1.1" // Spark 3 ...

    jellyfish::wind_chime:一个用于对字符串进行近似和语音匹配的python库

    Jellyfish是一个Python库,用于对字符串进行近似和语音匹配。 由James Turk &lt; &gt;和Michael Stephens撰写。 有关贡献者,请参见 。 有关文档,请参见 。 来源可从。 水母&gt; = 0.7仅支持Python 3,如果您需要...

Global site tag (gtag.js) - Google Analytics