改变世界的是这样一群人,他们寻找梦想中的乐园,当他们找不到时,他们亲手创造了它

Java中对比两个字符串的相似度

Java中对比两个字符串的相似度的方法, 以下整理了两个方式比对方法,同样的字符串不同的计算方式得到的结果也是不同的:

package test;
 
/**
 * 对比俩个字符串的相似度
 * @author sanshi
 */
public class StrUtil {
    /**
     * 获取最长子串 (参数顺序与字符串长短无关)
     * @param strA
     * @param strB
     * @return
     */
    public static String longestCommonSubstringNoOrder(String strA, String strB) {
        if(strA.length() >= strB.length()){
            return longestCommonSubstring(strA, strB);
        }else{
            return longestCommonSubstring(strB, strA);
        }
    }
 
    /**
     * 获取最长子串 (长串在前,短串在后)
     * @param strLong
     * @param strShort
     * @return
     * <p>summary</p>:较长的字符串放到前面有助于提交效率
     */
    private static String longestCommonSubstring(String strLong, String strShort) {
        char[] chars_strA = strLong.toCharArray();
        char[] chars_strB = strShort.toCharArray();
        int m = chars_strA.length;
        int n = chars_strB.length;
        int[][] matrix = new int[m + 1][n + 1];
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (chars_strA[i - 1] == chars_strB[j - 1]){
                    matrix[i][j] = matrix[i - 1][j - 1] + 1;
                }
                else{
                    matrix[i][j] = Math.max(matrix[i][j - 1], matrix[i - 1][j]);
                }
            }
        }
        char[] result = new char[matrix[m][n]];
        int currentIndex = result.length - 1;
        while (matrix[m][n] != 0) {
            if (matrix[n] == matrix[n - 1]) {
                n--;
            } else if (matrix[m][n] == matrix[m - 1][n]) {
                m--;
            } else {
                result[currentIndex] = chars_strA[m - 1];
                currentIndex--;
                n--;
                m--;
            }
        }
        return new String(result);
    }
 
    private static boolean charReg(char charValue) {
        return (charValue >= 0x4E00 && charValue <= 0X9FA5) || (charValue >= 'a' && charValue <= 'z') || (charValue >= 'A' && charValue <= 'Z') || (charValue >= '0' && charValue <= '9');
    }
 
    private static String removeSign(String str) {
        StringBuffer sb = new StringBuffer();
        for (char item : str.toCharArray()){
            if (charReg(item)) {
                sb.append(item);
            }
        }
        return sb.toString();
    }
 
    /**
     * 比较俩个字符串的相似度(方式一)
     * 步骤1:获取两个串中最长共同子串(有序非连续)
     * 步骤2:共同子串长度 除以 较长串的长度
     * @param strA
     * @param strB
     * @return 两个字符串的相似度
     */
    public static double SimilarDegree(String strA, String strB) {
        String newStrA = removeSign(strA);
        String newStrB = removeSign(strB);
        int temp = Math.max(newStrA.length(), newStrB.length());
        int temp2 = longestCommonSubstringNoOrder(newStrA, newStrB).length();
        return temp2 * 1.0 / temp;
    }
 
    /**
     * 第二种实现方式 (获取两串不匹配字符数)
     * @param str
     * @param target
     * @return
     */
    private static int compare(String str, String target) {
        int d[][]; // 矩阵
        int n = str.length();
        int m = target.length();
        int i; // 遍历str的
        int j; // 遍历target的
        char ch1; // str的
        char ch2; // target的
        int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        if (n == 0) {
            return m;
        }
        if (m == 0) {
            return n;
        }
        d = new int[n + 1][m + 1];
        // 初始化第一列
        for (i = 0; i <= n; i++) {
            d[i][0] = i;
        }
        // 初始化第一行
        for (j = 0; j <= m; j++) {
            d[0][j] = j;
        }
        // 遍历str
        for (i = 1; i <= n; i++) {
            ch1 = str.charAt(i - 1);
            // 去匹配target
            for (j = 1; j <= m; j++) {
                ch2 = target.charAt(j - 1);
                if (ch1 == ch2) {
                    temp = 0;
                } else {
                    temp = 1;
                }
 
                // 左边+1,上边+1, 左上角+temp取最小
                d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
            }
        }
        return d[n][m];
    }
 
    private static int min(int one, int two, int three) {
        return (one = one < two ? one : two) < three ? one : three;
    }
 
    /**
     * 比较俩个字符串的相似度(方式一)
     * 步骤1:获取两个串中不相同的字符数
     * 步骤2:不同字符数 除以 较长串的长度
     * @param strA
     * @param strB
     * @return
     */
    public static double similarityRatio(String strA, String strB) {
        return 1 - (double) compare(strA, strB) / Math.max(strA.length(), strB.length());
    }
 
 
    public static void main(String[] args){
        String strA = "河北唐山市协和医院";
        String strB = "河北省唐山协和医院";
 
        System.out.println(longestCommonSubstringNoOrder(strA,strB));
        System.out.println(SimilarDegree(strA,strB));
        System.out.println(compare(strA,strB));
        System.out.println(similarityRatio(strA,strB));
    }
 
}

示例代码输出结果如下:

河北唐山协和医院
0.8888888888888888
2
0.7777777777777778

 

posted @ 2023-05-06 10:20  水狼一族  阅读(1183)  评论(0编辑  收藏  举报
改变世界的是这样一群人,他们寻找梦想中的乐园,当他们找不到时,他们亲手创造了它