计算字符串的距离 --- 动态规划

计算字符串的距离

    • 计算字符串的距离
    • 解题思路
    • 代码实现

计算字符串的距离

【计算字符串的距离】
Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插
入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家Levenshtein提出的,故又叫Levenshtein Distance。
Ex:
字符串A:abcdefg
字符串B: abcdef
通过增加或是删掉字符”g”的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。
要求:
给定任意两个字符串,写出一个算法计算它们的编辑距离。
请实现如下接口
/* 功能:计算两个字符串的距离
*输入: 字符串A和字符串B
*输出:无
*返回:如果成功计算出字符串的距离,否则返回-1
*/
public static int calStringDistance (String charA, String charB)
{
return 0;
}

计算字符串的距离 --- 动态规划_第1张图片

解题思路

解读题目

可用的操作:插入、删除、替换

一次操作:只能操作一个字符

编辑距离:最小的操作次数


动态规划

问题:字符串A转换成字符串B的编辑距离

子问题:字符串A的一部分转化为字符串B的一部分的编辑距离

状态F(i,j) :字符串A的前i个字符转换成字符串B的前j个字符的编辑距离

分析状态转移

F(i,j):A[1,i] - > B[1,j],将字符串A的第一个字符到第i个字符,转化为,字符串B的第一个字符到第j个字符

  • 插入操作:F(i,j-1) : A[1,i] -> B[1,j-1] + 插入第j个字符

  • 删除操作:F(i-1,j) : A[1,i-1] -> B[1,j] + 删除第i个字符

  • 替换操作:F[i-1,j-1] : A[1,i-1] -> B[1,j-1] +
    ……如果A[i]等于B[j],则不替换
    ……如果A[i]不等于B[j],则把A的第i个字符替换为B的第j个字符

最终要比较最小的 min(插入,删除,替换)操作

所以得出状态转移方程

F(i,j) = min (F(i,j-1) + 1 , F(i-1,j) + 1 , F(i-1,j-1) + (A[i] == B[j] ? 0 : 1))

初始状态:F(0,j) = j (插入操作)、F(i,0) = i(删除操作)

代码实现

import java.util.*;

public class Main {
     
    public static void main(String[] args) {
     
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
     
            String str1 = scanner.nextLine();
            String str2 = scanner.nextLine();
            int res = calStringDistance(str1,str2); //调用求最小步数函数
            System.out.println(res);
        }
    }

    //计算最小步数函数
    public static int calStringDistance(String str1, String str2) {
     
        //定义dp数组,行多加一行,列多加一列,因为存放初始状态,用来辅助比较
        int[][] step = new int[str1.length()+1][str2.length()+1];
        //初始列:F(i,0) = i(删除操作)
        for (int i = 0; i < step.length; i++) {
     
            step[i][0] = i;
        }
        //初始行:F(0,j) = j (插入操作)
        for (int i = 0; i < step[0].length; i++) {
     
            step[0][i] = i;
        }
        //开始转换DP动态规划,遍历二维数组
        for (int i = 1; i < step.length; i++) {
     
            for (int j = 1; j < step[0].length; j++) {
     
                //如果A[i] == B[j],则不用增加步数,等于上一步 F(i-1,j-1)即可
                //如果A[i] != B[j],则需要比较三种操作中最小的步数,F(i,j) = min (F(i,j-1) , F(i-1,j) , F(i-1,j-1)) + 1
                if (str1.charAt(i-1) == str2.charAt(j-1)) {
     
                    step[i][j] = step[i-1][j-1];
                }else {
     
                    step[i][j] = Math.min(Math.min(step[i - 1][j], step[i - 1][j - 1]), step[i][j - 1]) + 1;
                }
            }
        }
        //返回二维数组DP的右下角,即遍历完两个字符串的最小步数
        return step[step.length - 1][step[0].length - 1];
    }
}

你可能感兴趣的:(刷题,字符串,算法,java,动态规划,dp)