当百度搜索错误时,下方会有提示,你要找的是不是xxx?
这样的一个功能是怎么实现的呢?
从最简单的思路出发,维护一套关键词词库,当搜索时,去与词库比较,哪一个最相似即可。
关键就在于最相似,如何实现?这就需要编辑算法了。

每步只能执行如下3个操作中的一个,
插入一个字符
删除一个字符
替换一个字符
将如图的word1换成word2最少需要几步。这就是编辑算法。
求word1转换成word2最少步骤的基本思路
下面是递归实现
/**
* 递归
*
* @param a
* @param b
* @return
*/
public static int recursion(String a, String b) {
if (a.length() * b.length() == 0) {
return a.length() + b.length();
}
if (a.substring(a.length() - 1).equals(b.substring(b.length() - 1))) {
return recursion(a.substring(0, a.length() - 1), b.substring(0, b.length() - 1));
} else {
int insert = recursion(a, b.substring(0, b.length() - 1));
int delete = recursion(a.substring(0, a.length() - 1), b);
int replace = recursion(a.substring(0, a.length() - 1), b.substring(0, b.length() - 1));
return Math.min(Math.min(insert, delete), replace) + 1;
}
}
需要理解,一旦涉及子问题,可以使用自顶向下的递归,或者,自底向上的动态规划。
想要使用动态规划,先要抽象出状态转移方程。
word1与word2是两个对应的状态,所以一定是二维状态数组。
抽象出状态转移方程
dp表示dynamicProgramming
动态规划实现如下
/**
* 动态规划
*
* @param a
* @param b
* @return
*/
public static int dynamicProgramming(String a, String b) {
int m = a.length();
int n = b.length();
if (m * n == 0) {
return m + n;
}
//列和行,各新增一个空。一列有n+1行,一行有m+1列
int[][] d = new int[n + 1][m + 1];
for (int i = 0; i < m + 1; i++) {
d[0][i] = i;
}
for (int j = 0; j < n + 1; j++) {
d[j][0] = j;
}
for (int i = 1; i < n + 1; i++) {
for (int j = 1; j < m + 1; j++) {
int replace = d[i - 1][j - 1];
int insert = d[i][j - 1];
int delete = d[i - 1][j];
if (a.charAt(j - 1) == b.charAt(i - 1)) {
d[i][j] = replace;
} else {
d[i][j] = Math.min(Math.min(insert, delete), replace) + 1;
}
}
}
return d[n][m];
}

假设两个转换的串,最长的一个串长度为n。
从最坏的角度出发,
递归时间复杂度为3^n,
动态规划时间复杂度n^2

当n越大时,动态规划的优势就越明显。