编辑距离

/**
 * 给出字符串:str1、str2;判断这两个字符串的相似度有多大;
 * 编辑距离:可通过增删改,将str1操作某一或某几个字符转换成str2,其中改变最小的距离,为最优。
 * Dp规划实现编辑距离的相似度测算
 * 空间复杂度:O(mn)
 * 时间复杂度:O(mn)
 * @author Administrator
 */
public class EditDistanceUtils {

    /**
     * Dp规划实现的编辑距离
     * 步骤:
     * 1、构建一个二维数组;
     * 2、初始化input、target中每个字符的索引位置,分别初始化值的位置是第一行与第一列,表示input与target;
     * 3、根据判断,算出对应二维数组坐标处对应的编辑距离;(这里的距离,就是距离目标的字符的索引数值差)
     * 4、最后的对角值即为最终编辑距离的结果
     * **/
    private static int getEditDistance(String input, String target){
        try {
            int m = input.length();
            int n = target.length();
            if(m <= 0){
                return n;
            }
            if(n <= 0){
                return m;
            }
            //构建二维数组,并初始化
            int[][] matrix = new int[m][n];
            for(int i = 0; i < m; ++i){
                matrix[i][0] = i;
            }
            for(int i = 0; i < n; ++i){
                matrix[0][i] = i;
            }
            //遍历整个二维数组,获取每个字符所在位置的编辑距离;因为要计算i-1、j-1的位置,故从i/j=1开始
            for(int i = 1; i < m; ++i){
                for(int j = 1; j < n; ++j){
                    int c = input.charAt(i) == target.charAt(j) ? 0 : 1;
                    //i-1、j-1是算上一个交叉点的位置坐标;i-1、j与i、j-1为相邻两侧,从索引处已经减1,故加1
                    matrix[i][j] = Math.min(matrix[i-1][j-1] + c, Math.min(matrix[i -1][j] + 1, matrix[i][j - 1] + 1));
                }
            }

            return matrix[m - 1][n - 1];
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 计算两个字符串的 相似度
     * **/
    public static Double getSimilarity(String input, String target){
        Integer distance = getEditDistance(input, target);

        Double similarity = 1 -  distance.doubleValue() / Math.max(input.length(), target.length());
        return similarity;
    }

    /**
     * 计算输入字符串,与其他多个字符串的相似度
     * **/
    public static Map getSimilarityMap(String input, String... targets){
        try{
            if(input.length() <= 0){
                return Collections.EMPTY_MAP;
            }
            if(targets == null || targets.length <= 0){
                return Collections.EMPTY_MAP;
            }
            LinkedHashMap linkedHashMap = new LinkedHashMap<>();
            String target = "";
            for(int i = 0; i < targets.length; ++i){
                target = targets[i];
                Double similarity = getSimilarity(input, target);
                linkedHashMap.put(target, similarity);
            }
            return linkedHashMap;
        }catch (Exception e){
            e.printStackTrace();
        }
        return Collections.EMPTY_MAP;
    }

    /**
     * 计算输入字符串,与其他多个字符串的相似度
     * **/
    public static Map getSimilarityMap(String input, Double limit, String... targets){
        try{
            Map linkedHashMap = getSimilarityMap(input, targets);
            List keyList =  linkedHashMap.keySet().stream().collect(Collectors.toList());
            LinkedHashMap limitMap = new LinkedHashMap<>();
            String key = "";
            Double value = 0D;
            for(int i = 0; i < keyList.size(); ++i){
                key = keyList.get(i);
                value = linkedHashMap.getOrDefault(key, 0D);
                if(value >= limit){
                    limitMap.put(key, value);
                }
            }
            return limitMap;
        }catch (Exception e){
            e.printStackTrace();
        }
        return Collections.EMPTY_MAP;
    }

    public static void main(String[] args) {

        getSimilarityMap("haizeiwang", 0.8D,"haizhughaiwang","haizaiwang","haizaiwatg");
    }

}

你可能感兴趣的:(编辑距离)