题目:
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
代码:
class Solution { public: int minDistance(string word1, string word2) { const int n1 = word1.size(); const int n2 = word2.size(); // initialization vector<vector<int> > dp(n1+1,vector<int>(n2+1,0)); dp[0][0] = 0; for ( int j=1; j<=n2; ++j ) dp[0][j] = dp[0][j-1]+1; for ( int i=1; i<=n1; ++i ) dp[i][0] = dp[i-1][0]+1; // dp process for ( int i=1; i<=n1; ++i ) { for ( int j=1; j<=n2; ++j ) { if ( word1[i-1]==word2[j-1] ) { dp[i][j] = dp[i-1][j-1]; } else { int rep = dp[i-1][j-1] + 1; // replace int del = dp[i-1][j] + 1; // delete int ins = dp[i][j-1] + 1; // insert dp[i][j] = std::min(rep,std::min(del, ins)); } } } return dp[n1][n2]; } };
tips:
不知道这是一个经典的DP案例,确实首次感到DP算法挺精妙的,很多无法想清楚理清楚的事情,交给DP就好了。
参考了两个网上blog的解释:
http://fisherlei.blogspot.sg/2012/12/leetcode-edit-distance.html
http://bangbingsyb.blogspot.sg/2014/11/leetcode-edit-distance.html
dp[i][j]表示s1[0~i-1]与s2[0~j-1]的编辑距离:
根据题意,计算dp[i][j]分如下几种情况:
1. 如果s1[i-1]==s2[j-1] 则不用三种操作,直接dp[i][j] = dp[i-1][j-1]
2. 如果s1[i-1]!=s2[j-1] 则需要在上几步的基础上进行匹配操作:
a) 如果直接选择替换则 dp[i][j] = dp[i-1][j-1] + 1
翻译过来就是:s1[0~i-2]与s2[0~j-2]已经对上了,把s1[i-1]的值换成s2[j-1]的值,替换之;
b) 如果选择删除操作则 dp[i][j] = dp[i-1][j] + 1
翻译过来就是:s1[0~i-2]与s2[0~j-1]已经对上了,这个s1[i-1]就是多余的了,删除之;
c) 如果选择插入操作则 dp[i][j] = dp[i][j-1] + 1
翻译过来就是:s1[0~i-1]与s2[0~j-2]已经对上了,因此少s1当前坐标后面再不上一个s2[j-1]这个值就OK了,插入之;
按照上述的过程,就可以写出来代码了。
为什么每次都加1呢?因为字符要一个一个匹配。
“插入”、“替换”、“删除”什么时候出现是有讲究的。最优的情况就是这些操作单独就可以完成转换,所以要选择出现的情况。