【编程题 动态规划】HJ52 计算字符串的编辑距离(详细注释 易懂)

题目描述

题目链接:计算字符串的编辑距离_牛客题霸_牛客网 (nowcoder.com)

Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。

例如:

字符串A: abcdefg

字符串B: abcdef

通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。

要求:

给定任意两个字符串,写出一个算法计算它们的编辑距离。

数据范围:给定的字符串长度满足 1 <= len(str) <= 1000

输入描述:

每组用例一共2行,为输入的两个字符串

输出描述:

每组用例输出一行,代表字符串的距离

示例1

输入:

abcdefg
abcdef

输出:

1

题目解读:

     给出两个字符串,要求通过最少的次数,把它们变成完全相同的字符串。求最少的次数是几次? 题目就这些,没什么特别的。

解题思想:

     读懂题目是第一步,怎么做这个题,容易想到的一个思路是 ,用双循环遍历,但这个思路,对于重复出现的字符也会重复计数,从而导致错误的结果,所以这个思路抛弃; 第二个思路是 用 两个 HashMap 分别存储每个字符串,然后遍历第一个 HashMap,拿出它的key值,和value值 与第二个HashMap 进行比较,如果第一个 HashMap 的key值 ,在第二个 HashMap 里找不到,那么就加上第一个HashMap 的 key 的 value 值 。如果第一个 HashMap 的key值 ,在第二个 HashMap 里的值非空,那就加上它俩 value值的 差值。  这个思路逻辑上没问题,但是执行起来有点麻烦,因为你得 引入 Map.Entry ,然后通过Entry里提供的获取key 和 value的方法 ,拿出来比较。

    那这里,我们就想到用动态规划法,但是这次的两个字符串比较与以往的字符串比较都不相同,所以按照以往的 动态规划解题,是解不出来的。 那我们还是得 分析这个题,如果比较两个字符串,它们中的 字符相等但不重复时,编辑距离不变,如果相等但重复,每重复一次,编辑距离加 1, 如果两个字符不相等,那就 加 1 ,当然这个 加 1,不是直接加,而是采用左邻右舍法 。具体如下图 。

【编程题 动态规划】HJ52 计算字符串的编辑距离(详细注释 易懂)_第1张图片

     给两个字符串前面加个空字符,然后上面是字符串1  abcde ,下面是 字符串2  bcdef 。 首先,给上边的一行 初始化数字,从1 到 n(n是字符串1 的长度),给左边的一列 初始化数字,从1 到 m(m是字符串2 的长度)。从左边一列的 b开始,它与字符串1的每个字符,进行比较,相等,编辑距离不变,与它们左上角的数字一致就行了, 也就是 [ i-1 ][ j-1 ] 的值。如果不相等,那就看    [ i-1 ][ j-1 ] ,[ i- 1][ j ] ,[ i ][ j ] ,看这三个里面的最小值,然后最小值加 1 ,这样就是字符串2 里,进行比较的字符,变成与字符串1 里已经比较的字符串相同的最少次数。   

代码注释:    

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        String str1 = scan.next();
        String str2 = scan.next();
        int length1 = str1.length();
        int length2 = str2.length();
       // 设一个二维数组,记录当前的编辑次数
        int[][] distance = new int[length1+1][length2+1];
       // 给字符串1 初始化
        for(int i=1;i<= length1;i++){
            distance[i][0] = i;
        }
        // 给字符串2 初始化
        for(int i=1;i<= length2;i++){
            distance[0][i] = i;
        }
        for(int i=1;i<= length1;i++){
            for(int j=1;j<= length2;j++){
                if(str1.charAt(i-1)== str2.charAt(j-1))
                    distance[i][j] = distance[i-1][j-1];
                else{
                // 不相等时,获取三个位置的 加1 后的 最小值
                    distance[i][j] = Math.min(distance[i-1][j-1]+1,
                            Math.min(distance[i][j-1]+1,distance[i-1][j]+1));
                }
            }
        }
       // 返回 最后一个位置
        System.out.println(distance[length1][length2]);
    }
}

你可能感兴趣的:(笔试刷题(详细注释,小白易懂),java,算法,数据结构)