首页 > 代码库 > Edit Distance

Edit Distance

一、     题目

         这道题是求一个字符串编辑成为另一个字符串的最少操作数,只有三种操作包括添加,删除或者替换一个字符。

二、     分析

这其实是一道二维动态规划的题目,维护的变量dp[i][j]表示的是word1的前i个字符和word2的前j个字符编辑的最少操作数是多少。我们分两种情况来讨论:

1)如果word1[i-1]=word2[j-1],也就是当前两个字符相同,那么也就是不需要编辑,则我们容易得到dp[i][j]=dp[i-1][j-1]

2)如果word1[i-1]!=word2[j-1],那么我们就需要考虑三种操作,如果是插入word1,那么dp[i][j]=dp[i-1][j]+1,也就是取word1前i-1个字符和word2前j个字符的最好结果,然后添加一个插入操作;如果是插入word2,那么dp[i][j]=dp[i][j-1]+1,同上面一种操作;如果是替换操作,那么类似于上面第一种情况,但是要加一个替换操作(因为word1[i-1]和word2[j-1]不相等),所以递推式是dp[i][j]=dp[i-1][j-1]+1。

上面列举的情况包含了所有可能性,在网上看到有人可能会说为什么没有删除操作,其实这里添加一个插入操作永远能得到与一个删除操作相同的效果,所以删除不会使最少操作数变得更好,因此如果我们是正向考虑,则不需要删除操作。取上面几种情况最小的操作数,即为第二种情况的结果,即dp[i][j] = min(dp[i-1][j], res[i][j-1], dp[i-1][j-1])+1。

分析下复杂度,算法时间上就是两层循环,所以时间复杂度是O(m*n)。

 

class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.size();
		int len2 = word2.size();
		
		if(len1 == 0) return len2;
		if(len2 == 0) return len1;
		
		int dp[len1+1][len2+2];
		//memset(dp,0,len1*len2*dp[0][0]);
		for(int i=0;i<len1;i++)
			for(int j=0;j<len2;j++)
				dp[i][j] = 0;		
		for(int i=0; i<=len1; i++)
			dp[i][0] = i;
		for(int j=0; j<=len2; j++)
			dp[0][j] = j;
		
		for(int i=1; i<=len1; i++){
			for(int j=1;j<=len2; j++){
				if(word1[i-1] == word2[j-1])
					dp[i][j] = dp[i-1][j-1];
				else 
					dp[i][j] = 1 + Min(dp[i-1][j-1],Min(dp[i-1][j],dp[i][j-1]));
				
			}
		}
		return dp[len1][len2];
    }
    
    int Min(int a, int b)
    {
    	if(a>b)
    		return b;
    	else
    		return a;
    }
};


Edit Distance