问题描述:算法
对于序列S和T, 它们之间的距离定义为: 对两者其一进行几回如下操做: 1, 删除一个字符; 2, 插入一个字符; 3, 改变一个字符. 每进行一次操做, 计数增长1. 将S和T变为相等序列的最小计数就是二者的编辑距离(edit distance)或者叫类似度. 请给出相应算法及其实现. 数组
分析:spa
假设序列S和T的长度分别为m和n, 二者的编辑距离表示为edit[m][n]. 则对序列进行操做时存在如下几种状况:3d
因此, 以上咱们不难推出编辑距离的动态规划方程为:code
, 其中
blog
因此, 字符串编辑距离的动态规划算法的递归实现能够用以下的Java代码表示:递归
1 public static int editDistance(String a, String b) { 2 if (a == null || b == null) { 3 return -1; 4 } 5 return editDistance(a, a.length() - 1, b, b.length() - 1); 6 } 7 8 public static int editDistance(String a, int m, String b, int n) { 9 if (m < 0 || n < 0) { 10 return 1; 11 } else if (a.charAt(m) == b.charAt(n)) { 12 return editDistance(a, m - 1, b, n - 1); 13 } else { 14 return Math.min(Math.min(editDistance(a, m - 1, b, n) + 1, editDistance(a, m, b, n - 1) + 1), editDistance(a, m - 1, b, n - 1) + 1); 15 } 16 }
UPDATE:字符串
同时, 由编辑距离的动态规划方程咱们能够看出, edit[m][n]能够由edit[m - 1][n - 1], edit[m - 1][n], edit[m][n - 1]得出, 而若是edit是一个二维数组的话, edit[m][n]能够由它的上, 左, 左上三个位置的元素经过条件判断得出. 亦即咱们能够经过遍历二维数组, 而后经过回溯来计算当前值.it
例如对于字符串S = "sailn"和T = "failing", 对二维数组进行初始化为:table
m\n | f | a | i | l | i | n | g | |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
s | 1 | 1 | ||||||
a | 2 | |||||||
i | 3 | |||||||
l | 4 | |||||||
n | 5 |
由于S[0] = s, T[0] = f, 则S[0] != T[0], 则对应于上述二维矩阵, edit[1][1] = min(edit[0][0], edit[0][1], edit[1][0]) + 1即edit[1][1] = min(0, 1, 1) + 1即edit[1][1] = 0 + 1 = 1.
m\n | f | a | i | l | i | n | g | |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
s | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
a | 2 | 2 | 1 | |||||
i | 3 | |||||||
l | 4 | |||||||
n | 5 |
而对于S[1] = a, T[1] = a, S[1] = T[1], 则对应于二维矩阵, edit[2][2] = edit[1][1], 因此edit[2][2] = 1. 因此按照这种规则, 将上述二维矩阵填满则以下:
m\n | f | a | i | l | i | n | g | |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
s | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
a | 2 | 2 | 1 | 2 | 3 | 4 | 5 | 6 |
i | 3 | 3 | 2 | 1 | 2 | 3 | 4 | 5 |
l | 4 | 4 | 3 | 2 | 1 | 2 | 3 | 4 |
n | 5 | 5 | 4 | 3 | 2 | 2 | 2 | 3 |
因此, 二者的编辑距离为edit[m][n] = edit[5][7] = 3.
因此, 按照上述思路即动态规划的回溯解法的Java版本能够以下进行:
1 public static int editDistance(String a, String b) { 2 if (a == null || b == null) { 3 return -1; 4 } 5 int[][] matrix = new int[a.length() + 1][b.length() + 1]; 6 for (int i = 0; i < a.length() + 1; i++) { 7 for (int j = 0; j < b.length() + 1; j++) { 8 if (i == 0) { 9 matrix[i][j] = j; 10 } else if (j == 0) { 11 matrix[i][j] = i; 12 } else { 13 if (a.charAt(i - 1) == b.charAt(j - 1)) { 14 matrix[i][j] = matrix[i - 1][j - 1]; 15 } else { 16 matrix[i][j] = 1 + Math.min(Math.min(matrix[i - 1][j], matrix[i][j - 1]), matrix[i - 1][j - 1]); 17 } 18 } 19 } 20 } 21 return matrix[a.length()][b.length()]; 22 }