两个字符串s1,s2通过修改,增加,删除任意个字符,使得两者相等,使得这个变动最少的次数就是编辑距离。
修改为第一类字符变动,增加/删除可以算同一种,因为你对s1+一个字符使得其于s2相等,其实就是等价于s2减一个字符
思路:
求 (s1,s2的编辑距离)
出口情况: 如果s1长度0,s2长度0,返回0
如果s1长0,返回s2的长度
如果s2长0,返回s1的长度
递归情况:第一,判断s1首个字符与s2首个字符是否相等,用first表示,等0,不等1
c1为(s1-char1与s2-char2的编辑距离)+first(修改情况)
第二 c2 为(s1-char1与s2编辑距离) +1(删s1第一个字符)
第三 c3为(s1与s2-char1编辑距离) + 1(删s2第一个字符)
返回getMin(c1,c2,c3)
补充:由于存在重复的子问题(三种情况的递归有重复的情况)。所以用一个缓存存储数据,解决重复子问题现象。即动态规划的方法。
程序
package com.java.ly2011.June;
public class StrEdit {
private static int method1Time;
private static int method2Time;
private static int getMin(int a ,int b){
return a<b?a:b;
}
public static int normalStrEdit(String s1 , String s2){
method1Time++;
if(s1.length()==0&&s2.length()==0)
return 0;
else if(s1.length()==0)
return s2.length();
else if(s2.length()==0)
return s1.length();
else{
char s1First = s1.charAt(0);
char s2First = s2.charAt(0);
int firstCharEdit = s1First==s2First?0:1;
int condition1 = normalStrEdit(s1.substring(1),s2.substring(1))+firstCharEdit;
int condition2 = normalStrEdit(s1, s2.substring(1))+1;
int condition3 = normalStrEdit(s1.substring(1), s2)+1;
return getMin(getMin(condition1, condition2), condition3);
}
}
/**
* cache数组 缓存结果,避免重复求解
* @param s1
* @param s2
* @param cache
* @return
*/
public static int DPStrEdit(String s1 , String s2 ,int[][] cache){
method2Time++;
if(s1.length()==0&&s2.length()==0){
cache[s1.length()][s1.length()]=0;
return 0;
}
else if(s1.length()==0){
cache[s1.length()][s2.length()]=s2.length();
return s2.length();
}
else if(s2.length()==0){
cache[s1.length()][s2.length()]=s1.length();
return s1.length();
}
else{
char s1First = s1.charAt(0);
char s2First = s2.charAt(0);
int firstCharEdit = s1First==s2First?0:1;
int condition1;
if(cache[s1.substring(1).length()][s2.substring(1).length()]!=-1)
condition1 = cache[s1.substring(1).length()][s2.substring(1).length()]+firstCharEdit;
else
condition1 = DPStrEdit(s1.substring(1),s2.substring(1),cache)+firstCharEdit;
int condition2;
if(cache[s1.length()][s2.substring(1).length()]!=-1)
condition2= cache[s1.length()][s2.substring(1).length()]+1;
else
condition2= DPStrEdit(s1, s2.substring(1),cache)+1;
int condition3;
if(cache[s1.substring(1).length()][s2.length()]!=-1)
condition3= cache[s1.substring(1).length()][s2.length()]+1;
else
condition3= DPStrEdit(s1.substring(1), s2,cache)+1;
int result = getMin(getMin(condition1, condition2), condition3);
cache[s1.length()][s2.length()] = result;
return result;
}
}
public static void main(String[] args) {
String s1 = "abcd";
String s2 = "efcod";
//method1
System.out.println(normalStrEdit(s1, s2));
System.out.println(method1Time);//1021
//method2
int[][] a = new int[s1.length()+1][s2.length()+1];//s1(0个元素到4个元素)s2(0个元素到5个元素) 5*6矩阵
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
a[i][j] = -1;
}
}
System.out.println(DPStrEdit(s1, s2, a));
System.out.println(method2Time);//30
}
}