编辑距离是比较经典的动态规划问题 指的是将一个字符创S1通过增删改的方式转为S2,比如将
rad转化为apple 则最少需要5步 即删除R,跳过A,将D转为P,增加P,增加L,增加E
动态规划解法如下
public class TEST编辑距离 {
//对一个字符串进行3种操作 插入 删除 替换 ,给定2个字符串 计算将s1转换为S2最少需要几次操作
//这里是将S1 变成S2
static int mindistance(String s1,String s2){
int m=s1.length(),n=s2.length();
//dp的定义 S1[0...i] 和S2[0...j]的最短编辑距离为dp[i][j]
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]=min(dp[i-1][j]+1,//插入 在I这个位置插入一个和J相同的元素
dp[i][j-1]+1,//删除 在I这个位置删除 使得保持一致
dp[i-1][j-1]+1);//修改 使得i和j 的元素相同
}
}
}
return dp[m][n];
}
static int min(int a ,int b,int c){
return Math.min(a,Math.min(b,c));
}
public static void main(String[] args) {
String s1="rad";
String s2="apple";
int i = mindistance(s1, s2);
System.out.println(i);
}
}
动态规划如上 可以看到dp[I]][J]的状态只与dp[i-1][j-1],dp[i-1][j],dp[i][j-1]y有关,因此可以使用状态压缩进一步降低空间复杂度
状态压缩如下:
public class TEST编辑距离 {
//对一个字符串进行3种操作 插入 删除 替换 ,给定2个字符串 计算将s1转换为S2最少需要几次操作
//这里是将S1 变成S2
//状态压缩
static int mindistance2(String s1,String s2){
int m=s1.length();
int n=s2.length();
if(m==0)
return n;
if(n==0)
return m;
int[] dp=new int[n+1];
for(int i=0;i<=n;i++)
dp[i]=i;
for(int i=1;i<=m;i++){
int pre=1;
for(int j=1;j<=n;j++){
if(j==1)
dp[j-1]=i;
int temp=pre;
pre=dp[j];
//int temp=dp[j];
if(s1.charAt(i-1)==s2.charAt(j-1)) {
dp[j]=temp;
}
else {
dp[j]=Math.min(Math.min(temp,dp[j]),dp[j-1])+1;
}
}
}
return dp[n];
}
public static void main(String[] args) {
String s1="rad";
String s2="apple";
int i = mindistance2(s1, s2);
System.out.println(i);
}
}