编辑距离定义
通过插入删除或替换使得一个字符串变为另一个字符串的最小操作次数。
DP思路
设有字符串a和字符串b
a[m]表示第一个字符串,m表示该字符串字符的下标为0~m
b[n]表示第二个字符串,n表示该字符串字符的下标为0~n
d[i][j]表示子串a[i]和子串a[j]的最小编辑距离
那么边界条件:
d[i][0]=i, 0=<i<=m
d[0][j]=j, 0=<j<=n
状态转移方程:
if(a[i-1]等于b[j-1]) d[i][j]=d[i-1][j-1]
else d[i][j] = min{d[i-1][j]+1,d[i][j-1]+1}
d[i-1][j]+1:代表a(0,i-1)变成b(0,j)时,a需减去多余的1个字符转到a(0,i-1),所以操作数+1
d[i][j-1]+1:代表a(0,i)变成b(0,j-1)时,a加上1个字符匹配到b(0,j),所以操作数+1
d[i-1][j-1]+1:代表将a的最后字符转成b的最后字符,所以操作+1
public static void main(String[] args) {
System.out.println(sditDistance("sailn", "failing"));
System.out.println(sditDistance("Louis", "Loisu"));
System.out.println(sditDistance("recoginze", "recognize"));
}
public static int sditDistance(String s1, String s2) {
final int m = s1.length();
final int n = s2.length();
int[][] d = new int[m + 1][n + 1];
for (int j = 0; j <= n; ++j) {
d[0][j] = j;
}
for (int i = 0; i <= m; ++i) {
d[i][0] = i;
}
// for (int[] l : d) {
// System.out.println(Arrays.toString(l));
// }
for (int i = 1; i <= m; ++i) {
char ci = s1.charAt(i - 1);
for (int j = 1; j <= n; ++j) {
char cj = s2.charAt(j - 1);
if (ci == cj) {
d[i][j] = d[i - 1][j - 1];
} else {
// 等号右边的分别代表 将ci改成cj 错串加cj 错串删ci
d[i][j] = Math.min(d[i - 1][j - 1] + 1, Math.min(d[i][j - 1] + 1, d[i - 1][j] + 1));
}
}
}
// System.out.println();
// for (int[] l : d) {
// System.out.println(Arrays.toString(l));
// }
return d[m][n];
}