算法:LevenshteinDistance编辑距离:两个字符串的相似度,Java实现

编辑距离Levenshtein):两个字符之间有一个转成另一个所用的最少的编辑操作次数,操作包括:替换插入删除一个字符。 

定义:

算法:LevenshteinDistance编辑距离:两个字符串的相似度,Java实现_第1张图片

       

原理:
首先考虑极端情况,当或长度为0时,那么需要编辑的次数就是里一个字符串的长度。

然后再考虑一般情况,此时分为三种情况:

在k个操作中,将a[1...i]转换为b[1...j-1]:例如:a(abc)    b(abcd)
在k个操作中,将a[1...i-1]转换为b[1...j]:例如:a(abc)    b(ab)
在k个操作中,将a[1...i-1]转换为b[1...j-1]:例如:a(abc)   b(abb)
针对第一种情况,只需要在a[1...i]后加上字符b[j],即可完成a[1..i]到b[1...j]的转换,总共需要的编辑次数即为k+1。

针对第二种情况,只需要在a[i]字符从a中移除,即可完成a[1..i]到b[1...j]的转换,总共需要的编辑次数即为k+1。

针对第三种情况,只需要将a[i]转换为b[j],即可完成a[1..i]到b[1...j]的转换,如果a[i]与b[i]的字符相同,则总共需要的编辑次数为k,否则即为k+1。

所以上述三种情况分别对应于插入、删除、替换操作。

为了保证将a[1..i]转换为b[1..j]的操作数总是最少的,只需要从三种情况中选择操作次数最少的情况,同理为了保证三种情况的操作数也是最小的,只需要按此逻辑进行迭代保证每一步的操作数都是最小的即可。

String left="helloword";
String right="hellowo";

 

代码:

package com.parse;

public class Test3 {

    public static void main(String args[]){
        String left="helloword";
        String right="hellowo";
        int maxLength = Math.max(left.length(), right.length());
        //计算编辑距离
        double lev = unlimitedCompare(left, right);
        System.out.println("编辑距离:"+lev);
        //计算相似度
        double levNorm = 1 - (lev / maxLength);

        System.out.println("相似度:"+levNorm);
    }

    public static int unlimitedCompare(CharSequence left, CharSequence right) {
        if (left == null || right == null) {
            throw new IllegalArgumentException("Strings must not be null");
        }

        int n = left.length();
        int m = right.length();
        //如果有一个String长度为0,则编辑长度为另一个String长度
        if (n == 0) {
            return m;
        } else if (m == 0) {
            return n;
        }

        int [][] dp = new int [n+1][m+1];   //动态规划数组
        int i;//left的索引
        int j;//right的索引

        char leftI; // left字符串第i项字符
        char rightJ; // right字符串第j项字符
        int cost;   //操作代价

        //初始化第一列
        for (i = 0; i <= n; i++)
        {
            dp[i][0] =i;
        }
        //初始化第一行
        for (j = 0; j <= m; j++)
        {
            dp[0][j] = j;
        }

        for (i = 1; i <= n; i++) {
            leftI =left.charAt(i - 1);
            for (j = 1; j <= m; j++) {
                rightJ = right.charAt(j - 1);

                //从i看是否和rightJ相同,所需要的操作代价,不同就会+1,相同为0
                cost = leftI == rightJ ? 0 : 1;
                //取dp[i - 1][j] + 1,dp[i][j-1] + 1, dp[i-1][j-1] + cost这三者中最小的
                dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j-1] + 1), dp[i-1][j-1] + cost);

            }
        }

        return dp[n][m];
    }
}

 感觉理解了?    想想下面的编辑距离为啥是2,而不是3?

String left="abroad";
String right="aboard";
String left="abroad";
String right="aboadr";

 

不理解的话,看看文章开头第一句话中的“最少”二字。 

你可能感兴趣的:(算法,Levenshtein,Distance,编辑距离)