【Edit Distance】cpp

题目:

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呢?因为字符要一个一个匹配。

“插入”、“替换”、“删除”什么时候出现是有讲究的。最优的情况就是这些操作单独就可以完成转换,所以要选择出现的情况。

=============================================

第二次过这道题,一开始忘记了word1[i-1]==word2[j-1]的情况,改了之后AC了。

class Solution {
public:
    int minDistance(string word1, string word2) {
            if ( word1==word2 ) return 0;
            int dp[word1.size()+1][word2.size()+2];
            fill_n(&dp[0][0], (word1.size()+1)*(word2.size()+1), 0);
            for ( int i=1; i<=word1.size(); ++i ) dp[i][0] = dp[i-1][0]+1;
            for ( int i=1; i<=word2.size(); ++i ) dp[0][i] = dp[0][i-1]+1;
            // dp process
            for ( int i=1; i<=word1.size(); ++i )
            {
                for ( int j=1; j<=word2.size(); ++j )
                {
                    if ( word1[i-1]==word2[j-1] ) 
                    {
                        dp[i][j] = dp[i-1][j-1];
                        continue;
                    }
                    // insert
                    int ins = dp[i][j-1]+1;
                    // delete
                    int del = dp[i-1][j]+1;
                    // replace
                    int rep = dp[i-1][j-1]+1;
                    dp[i][j] = min(ins,min(del,rep));
                }
            }
            return dp[word1.size()][word2.size()];
    }
};

 

posted on 2015-06-04 10:10  承续缘  阅读(184)  评论(0编辑  收藏  举报

导航