[LeetCode29]Edit distance

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

Analysis:

刚看到这个题的时候,首先想到的是求最大公共子串,然后用最长字符串的长度减去最大公共子串长度,并写了code,但是随后测试case的时候,发现有问题。
比如A= “ab”, B="bc", 最大子串为“b”, 长度为1。但是如果把A转成B,需要2步,减a加c。
可见,最长子串并没有考虑到子串的差异,有可能带来多个操作。
解法仍然是二维DP,只不过转换方程有变化。
如果是求最长子串,方程是:
                    
dp[i][j] =  dp[i-1][j-1] +1  if (A[i] == B[j])
           or = max(dp[i][j-1], dp[i-1][j]);
初始条件: dp[0][j] = 0, dp[i][0] = 0

但对于编辑距离的话, 当我们要计算d(i,j)时,即计算A(i)到B(j)之间的编辑距离, 此时,设A(i)形式是somestr1c;B(i)形如somestr2d的话,
      将somestr1变成somestr2的编辑距离已知是d(i-1,j-1)
    将somestr1c变成somestr2的编辑距离已知是d(i,j-1)
    将somestr1变成somestr2d的编辑距离已知是d(i-1,j)
    那么利用这三个变量,就可以递推出d(i,j)了:
    如果c==d,显然编辑距离和d(i-1,j-1)是一样的
    如果c!=d,情况稍微复杂一点,
    1. 如果将c替换成d,编辑距离是somestr1变成somestr2的编辑距离 + 1,也就是d(i-1,j-1) + 1
    2. 如果在c后面添加一个字d,编辑距离就应该是somestr1c变成somestr2的编辑距离 + 1,也就是d(i,j-1) + 1
    3. 如果将c删除了,那就是要将somestr1编辑成somestr2d,距离就是d(i-1,j) + 1
      那最后只需要看着三种谁最小,就采用对应的编辑方案了。
    transition function:
    dp[i][j] =  dp[i-1][j-1]   if (A[i] == B[j])
               or = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) +1;
     initialtion condition: dp[0][j] = j and dp[i][0] = i 
Java

public int minDistance(String word1, String word2) {
       int s1 = word1.length();
		int s2 = word2.length();
		if(s1 == 0) return s2;
		if(s2 == 0) return s1;
		int [][]dis = new int[s1+1][s2+1];
		for(int i=0;i<=s1;i++)//init condition
			dis[i][0] = i;
		for(int i=0;i<=s2;i++)
			dis[0][i] = i;
		for(int i=1;i<=s1;i++){
			for(int j=1;j<=s2;j++){
				
				if(word1.charAt(i-1)==word2.charAt(j-1)){
					dis[i][j] = dis[i-1][j-1];
				}else {
					int temp = Math.min(dis[i-1][j], dis[i][j-1]);
					dis[i][j] = Math.min(dis[i-1][j-1], temp)+1;
				}
			}
		}
		return dis[s1][s2]; 
    }
c++

int minDistance(string word1, string word2) {
   int s1 = word1.size();
    int s2 = word2.size();
    if(s1 == 0)
        return s2;
    if(s2 == 0)
        return s1;
    vector<int> *dp = new vector<int>[s2+1];
    for(int i=0;i<=s1;i++)
        dp[0].push_back(i);
    for(int i=0;i<=s2;i++)
        dp[i].push_back(i);
    for(int i=1;i<=s2;i++){
        for(int j=1;j<=s1;j++){
            int n1 = word2[i-1]!=word1[j-1]?(dp[i-1][j-1]+1):dp[i-1][j-1];
            int n2 = dp[i-1][j]<dp[i][j-1]?(dp[i-1][j]+1):(dp[i][j-1]+1);
            dp[i].push_back(n1<n2? n1:n2);
        }
    }
    return dp[s2][s1];
    }



你可能感兴趣的:(LeetCode,dp,动态规划)