zoukankan      html  css  js  c++  java
  • 字符串相似度计算----编辑距离

    题目描述:

    要求两字符串有差异的字符个数。例如: 
    aaaaabaaaaa 
    aaaaacaabaa 
    这两个字符串,最大公共字串长度是5,但它们只有两个字符不同,函数输出值应为2。 
    如果是: 
    aaabbbcccddd 
    aaaeeeddd 
    函数的输出值应该是6。 

    比较形象地形容一下,把两个字符串排成上下两行,每个字符串都可以在任何位置插入空格以便上下对齐,每个列上至少有一个字符来自这两个字符串。当对齐程度最高的时候,没有对上的列的数即为函数输出值。 
    aaabbbcccddd 
    aaaeeeddd 
    最优对齐状态是: 
    aaabbbcccddd 
    aaaeee     ddd 
    没有对上的列是6,函数输出值为6。 
    如果是: 
    abcde 
    acefg 
    最优对齐状态是: 
    abcde 
    a  c  efg 
    没有对上的列数是4,函数输出值为4。

    问题抽象归类:(编辑距离问题)

    设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括:

    (1)删除一个字符;
    (2)插入一个字符;
    (3)将一个字符改为另一个字符。
    将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。
    要求:
    输入:第1行是字符串A,第2行是字符串B。
    输出:字符串A和B的编辑距离d(A,B)

    思路:动态规划

    开一个二维数组d[i][j]来记录a0-ai与b0-bj之间的编辑距离,要递推时,需要考虑对其中一个字符串的删除操作、插入操作和替换操作分别花费的开销,从中找出一个最小的开销即为所求

    具体算法:

    首先给定第一行和第一列,然后,每个值d[i,j]这样计算:d[i][j]   =   min(d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+(s1[i]  ==  s2[j]?0:1));   
     最后一行,最后一列的那个值就是最小编辑距离 

    package com.kunlun.bd.util;
    
    /** 
     * java 两字符串相似度计算算法  Levenshtein Distance编辑距离算法      
    * 
     * @author jianpo.mo 
     */ 
    public class Similarity { 
    
        private static int min(int one, int two, int three) { 
            int min = one; 
            if(two < min) { 
                min = two; 
            } 
            if(three < min) { 
                min = three; 
            } 
            return min; 
        } 
        
        public static int ld(String str1, String str2) { 
            int d[][];    //矩阵 
            int n = str1.length(); 
            int m = str2.length(); 
            int i;    //遍历str1的 
            int j;    //遍历str2的 
            char ch1;    //str1的 
            char ch2;    //str2的 
            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; 
            } 
            for(i=1; i<=n; i++) {    //遍历str1 
                ch1 = str1.charAt(i-1); 
                //去匹配str2 
                for(j=1; j<=m; j++) { 
                    ch2 = str2.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]; 
        } 
        
        public static double sim(String str1, String str2) { 
            int ld = ld(str1, str2); 
            return 1 - (double) ld / Math.max(str1.length(), str2.length()); 
        } 
        
        public static void main(String[] args) { 
           
            String str1="江苏-南通~江苏-泰州~在外面外面浴室过夜,昨晚包夜跟人打架被赶出来,没地方去就到浴室睡觉了!你今天什么时候考试啊?      ";
    
            String str2="在外面外面浴室过夜,昨晚包夜跟人打架被赶出来,没地方去就到浴室睡觉了!你今天什么时候考试啊?";
    
            System.out.println("ld="+ld(str1, str2)); 
            System.out.println("sim="+sim(str1, str2)); 
        } 
    } 
  • 相关阅读:
    5种Python使用定时调度任务的方式
    基于Tensorflow + Opencv 实现CNN自定义图像分类
    CANN 5.0硬核技术抢先看
    大力出奇迹,揭秘昇腾CANN的AI超能力
    MSQL:超强的多任务表示学习方法
    Shell:Lite OS在线调试工具知多少
    带你掌握Vue过滤器filters及时间戳转换
    Selenium系列(六) 详细解读强制等待、隐式等待、显式等待的区别和源码解读
    Linux常用命令 top命令详解(重点)
    Selenium系列(一) 详细解读8种元素定位方式
  • 原文地址:https://www.cnblogs.com/bendantuohai/p/4650454.html
Copyright © 2011-2022 走看看