问题描述:
/**
* Given two words word1 and word2, find the minimum number of steps required to
* convert word1 to word2. (each operation is counted as 1 step.)
*
* You have the following 3 operations permitted on a word:
*
* a) Insert a character
* b) Delete a character
* c) Replace a character
*/
两个字符串的相似度就是计算一个字符串转化为另一个字符串需要的步数steps,插入一个字符算一步,删除一个字符算一步,替换一个字符算一步。所以也叫作编辑距离。
很明显这是一个动态规划问题。声明一个数组arr[i][j]表示字符串word1[0…i-1]到word2[0…j-1]的距离。
在arr[i+1][j+1]和arr[i][j]之间有一个关系,比如word1结束字符为x,word2结束字符为y:
如果x=y,则arr[i+1][j+1]=arr[i][j];
如果x!=y,则我们可以从word1里删除一个元素,arr[i+1][j+1]=arr[i+1][j]+1;
我们也可以从word1插入一个元素,arr[i+1][j+1]=arr[i][j+1]+1;
我们也可以从word1替换一个元素,arr[i+1][j+1]=arr[i][j]+1;
我们可以用下图来解释一下上面的公式:
a p p l e
0 1 2 3 4 5
a 1 0 1 2 3 4
p 2 1 0 1 2 3
p 3 2 1 0 1 2
首先要初始化arr数组,arr[i][0]=i,arr[0][j]=j;这样初始化的含义对照上图就是说,arr[i][0]=i;即如果word2为空,那么要把word2转化为app,分别需要0,1,2,3步,也就是word2增加’a’,增加’p’,增加’p’。
arr[0][j]表示,word1从无到转化为word2 “apple”需要0,1,2,3,4,5步,即增加’a’,增加’p’,增加’p’,增加’l’,增加’e’。
word1的一个字符想要转化成word2,有3种方法:替换,删除,增加
每次转化时都要加1,因为这算1步。这样上面三个公式得以解决。
具体代码如下:
public int minDistance(String word1, String word2) {
if (word1.length() == 0 || word2.length() == 0)
return word1.length() == 0 ? word2.length() : word1.length();
int[][] arr = new int[word1.length() + 1][word2.length() + 1];
for (int i = 0; i <= word1.length(); i++) {
arr[i][0] = i;
}
for (int j = 0; j <= word2.length(); j++) {
arr[0][j] = j;
}
for (int i = 0; i < word1.length(); i++) {
for (int j = 0; j < word2.length(); j++) {
if (word1.charAt(i) == word2.charAt(j)) {
arr[j + 1][i + 1] = arr[j][i];
} else {
int replace = arr[i][j]+1 ;
int insert = arr[i][j + 1]+1 ;
int delete = arr[i + 1][j]+1 ;
int min = replace > insert ? insert : replace;
min = delete > min ? min : delete;
arr[i + 1][j + 1] = min;
}
}
}
return arr[word1.length()][word2.length()];
}