二、字符串相似度/编辑距离(edit distance)
对于序列S和T,它们之间距离定义为:对二者其一进行几次以下的操作
(1)删去一个字符
(2)插入一个字符
(3)改变一个字符
每进行一次操作,计数增加1。将S和T变为同一个字符串的最小计数即为它们的距离。给出相应算法。
问题分析:
这个问题就不像硬币找零问题能非常直观的想到如何分解成规模更小的问题,而且如何表示子问题的结果也是一个问题。
1. 求问题的最优解:最小的距离
2. 是否有子问题:
1)如果两个序列的最后一个元素相同。则S和T的距离等于S-1和T-1的距离。
2)由1)启发,如果最后一个元素不同,则D[S][T]=min(D[S-1][T-1), D[S][T-1),D[S-1][T]]+1;
3. 确定最小问题的解。
如果两个序列有一个序列长度为0的序列,那么这两个序列的距离就是长度不为0序列的长度。如果都为0,则距离为0。
5 从上往下分析问题,从下往上解决问题。
package dataStructureAndAlgorithms; public class DistanceOfStrings { /** * * @param S 全量字符串数组 * @param sLen 待计算距离的字符串的字符个数,从开始位置起。 * @param T 全量字符串数组 * @param tLen 待计算距离的字符串的字符个数,从开始位置起。 * @return */ public static int distance(char[] S, int sLen, char[] T, int tLen){ if(sLen == 0){ return tLen; } if(tLen == 0){ return sLen; } if(S[sLen-1] == T[tLen-1]){ return distance(S, sLen-1, T, tLen-1); } return min(distance(S, sLen-1, T, tLen-1), distance(S, sLen, T, tLen-1), distance(S, sLen-1, T, tLen)) + 1; } public static int min(int a, int b, int c){ return a<b?(a<c?a:c):(b<c?b:c); } public static void main(String[] args) { char[] S = "abc".toCharArray(); char[] T = "".toCharArray(); System.out.println(distance(S, S.length, T, T.length)); //1 S = "abc".toCharArray(); T = "abcd".toCharArray(); System.out.println(distance(S, S.length, T, T.length)); //1 S = "abcd".toCharArray(); T = "abxd".toCharArray(); System.out.println(distance(S, S.length, T, T.length)); //3 S = "abcd".toCharArray(); T = "abxdbcd".toCharArray(); System.out.println(distance(S, S.length, T, T.length)); } }