加载中…
个人资料
enjoydata
enjoydata
  • 博客等级:
  • 博客积分:0
  • 博客访问:395,396
  • 关注人气:29
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

字符串相似算法-Jaro-Winkler Distance

(2016-08-23 11:07:38)
标签:

字符串相似

算法

jaro-winklerdistance

分类: 数据挖掘

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;

  }


 

  public void setThreshold(float threshold) {

    this.threshold = threshold;

  }


 

  public float getThreshold() {

    return threshold;

  }

}

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有