描述
Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。
Ex:
字符串A: abcdefg
字符串B: abcdef
通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。
要求:
给定任意两个字符串,写出一个算法计算它们的编辑距离。
import java.util.Scanner;
public class Main {
public static int optTime = 0;
/**
* 初步思路(没有考虑全面):动态规划,若str1和str2,第一个字符相同,则清除继续递归判断剩下的,若不相同则删除str1第一个字符,并操作加1,用剩下的与str2继续递归。
* 字符不同的情况,有三种,用一个全局变量无法接收。
*/
public static void calOptTime(String str1,String str2) {
// 多或少出来的需要加减操作,多几个加几次
if(str1.length() == 0) {
optTime += str2.length();
// 多或少出来的需要加减操作,多几个加几次
} else if(str2.length() == 0) {
optTime += str1.length();
} else {
// 相同则,去掉相同继续递归
if(str1.charAt(0) == str2.charAt(0)) {
str1 = str1.substring(1, str1.length());
str2 = str2.substring(1, str2.length());
calOptTime(str1, str2);
} else {
// 不相同,减、加、或者替换操作,去掉str1的不同,继续递归(此处需要,三种情况下取最小,故:全局变量不能表达,需要状态数组等存储)
str1 = str1.substring(1, str1.length());
calOptTime(str1, str2);
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = 1;
String frist = "";
String second = "";
while(sc.hasNextLine()){
if(count % 2 != 0) {
frist = sc.nextLine();
} else {
// 重置操作次数(距离)
optTime = 0;
second = sc.nextLine();
calOptTime(frist, second);
System.out.println(optTime);
}
count++;
}
}
}
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
//输入字符串A
String s1=sc.next();
//输入字符串B
String s2=sc.next();
//计算字符串A和字符串B的距离
System.out.println(calOptTime(s1,s2));
}
}
private static int calOptTime(String s1,String s2){
int m=s1.length();
int n=s2.length();
//定义dp数组,用于存储记录两个字符串,对应i,j、i-1,j-1...长度下,对应的编辑距离dp[i][j]、dp[i-1][j-1]...
int[][] dp=new int[m+1][n+1];
//状态初始化,当一个字符串为空的时候,对应长度位置的编辑距离就是对应的字符串长度
for(int i=1;i<=m;i++){
dp[i][0]=i;
}
for(int j=1;j<=n;j++){
dp[0][j]=j;
}
//状态转移
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
//如果相等,直接等于前一个位置的情况
if(s1.charAt(i-1)==s2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1];
}
/*
* 如果不相等,取三种情况(见解题思路)最小的
*/
else{
dp[i][j] = Math.min(Math.min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1;
}
}
}
return dp[m][n];
}
}
正确思路参考链接:https://blog.nowcoder.net/n/8be215f4ba674af582320e2fc1c52503
总结:
动态规划:可能需要状态定义、状态存储(数组等)和状态转移式、递归、迭代思想、多种情况时,可能还需要用到max、min。