Edit Distance
problem:
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
solve:
需要用最少的操作来将一个字符串变成另一个字符串,很明显,采用动态规划的方法,解法同最大公共子串类似,首先可以设word1长度为i,word2长度为j, 令c[i][j]表示word1和word2的最短编辑距离,那么最优子结构如下:
当word1[i] == word2[j]时,很显然 c[i][j] =c[i-1][j-1],因为什么都不需要做。
当word1[i] != word2[j]时,根据题目中的条件,我们有三种操作:
1)替换操作,我们替换word1[i] 使其等于word2[j] 反之亦然,这样 c[i][j] =c[i-1][j-1] +1 这里加上1 就是我们做了一次操作。
2) 删除操作,我们可以把word1[i] 删掉,这样我们只需要比较word1[i-1] 和 word2[j]
这时 c[i][j] =c[i-1][j]+1
3 )和2)类似,我们删除word2[j] 这时c[i][j]=c[i][j-1]+1
我们从 1) 2) 3)中选择操作数最小的那个即可。可以得到如下公式
word1[i] == word2[j] c[i][j]=c[i-1][j-1]
word1[i] != word2[j] c[i][j]=min{c[i-1][j-1],c[i][j-1],c[i-1][j]}+1
i = 0 c[i][j]=j
j=0 c[i][j]=i
int minDistance(string word1, string word2) {
if(word1.size() ==0 && word2.size() == 0) return 0;
if(word1.size() == 0) return word2.size();
if(word2.size() == 0 ) return word1.size();
vector<int> cu;
vector<int> pr;
for(int i = 0 ; i <=word2.size(); i++)
{
pr.push_back(i);
cu.push_back(i);
}
for(int i = 1 ; i <=word1.size(); i++)
{
cu[0]=i;
for(int j = 1 ; j <=word2.size() ; j ++)
{
if(word1[i-1] == word2[j-1])
cu[j]=pr[j-1];
else
{
int min = cu[j-1]> pr[j]? pr[j]:cu[j-1];
min=min>pr[j-1]? pr[j-1]:min;
cu[j] =min+1;
}
}
pr=cu;
}
int len =cu[word2.size()];
return len;
上述代码中,由最优子结构表达式可以看出,我们虽然需要填满一个二维数组,可是每次操作只涉及本行与上一行,因此可以只用两行就可以。