动态规划法
算法描述
动态规划法,是将待解决的问题分解为若干个子问题(阶段),按顺序求解子阶段的结果,并且后一阶段的决策都要依赖前一子问题。利用动态规划法求取字符相似度的过程如下:- 用d[i,j]表示源字符串source[1..i]到目标target[1..j]之间的最小编辑距离,则计算d[i,j]的递推关系可以这样计算出来:
- 先初始化两组字符串:对source,d[i,0]=I;对target,d[0,j]=j。
如果source[i] 等于target[j],则:d[i,j]=d[i,j]+0
如果source[i] 不等于target[j],则根据插入、删除和替换三个策略,分别计算出使用三种策略得到的编辑距离,然后取最小的一个:d[i,j]=min(d[i,j−1]+1,d[i−1,j]+1,d[i−1,j−1]+1)
其中d[i,j-1]+1 表示对source[i]执行插入操作后计算最小编辑距离;
d[i-1,j]+1表示对source[i]执行删除操作后计算最小编辑距离 ;
d[i-1,j-1]+1表示对source[i]替换成target[i]操作后计算最小编辑距离。 - d[i,j]的边界值就是source为空或target为空时所计算出的编辑距离。
算法优缺
动态规划法计算字符串相似度,采用矩阵的方式计算编辑距离,计算过程中会遍历两个字符串的每一个字符,对其进行两两比较,时间复杂度至少为O(MN)。- java实现
/**
* 字符串工具类
* @author Y
*
*/
public class Str {
/**
* 通过动态规划算法获取两个字符串之间的相似度
* @param source 源字符串
* @param target 目标字符串
* @return source与target之间的相似度
*/
public static double getStrSimilarity(String source,String target){
double similarity = 1 - (double) getShortestDistance(source,target) / Math.max(source.length(), target.length());
return similarity;
}
/**
* 获取两个字符串之间的最短编辑距离
* @param source 源字符串
* @param target 目标字符串
* @return source与target之间的最短编辑距离
*/
public static int getShortestDistance(String source,String target){
int d[][];
int sourceLen = source.length();
int targetLen = target.length();
int distance;
// 提高效率,去除不影响正确性
if (sourceLen == 0) return targetLen;
if (targetLen == 0) return sourceLen;
// 初始化矩阵
d = new int[sourceLen + 1][targetLen + 1];
for (int i = 0; i <= sourceLen; i++) { d[i][0] = i; }
for (int j = 0; j <= targetLen; j++) { d[0][j] = j; }
// 遍历比较
for (int i = 0; i <= sourceLen - 1; i++) {
for (int j = 0; j <= targetLen - 1; j++) {
distance = source.charAt(i) == target.charAt(j) ? 0 : 1;
d[i + 1][j + 1] = Math.min(Math.min(d[i][j + 1] + 1, d[i + 1][j] + 1), d[i][j] + distance);
}
}
return d[sourceLen][targetLen];
}
}