首页 > 试题广场 >

编辑距离

[编程题]编辑距离
  • 热度指数:14701 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给定两个单词word1和word2,请计算将word1转换为word2至少需要多少步操作。
你可以对一个单词执行以下3种操作:
a)在单词中插入一个字符
b)删除单词中的一个字符
c)替换单词中的一个字符
示例1

输入

"b",""

输出

1
示例2

输入

"ab","bc"

输出

2
public class Solution {
    /*
    * 对于w1的第i位和w2的第j位,Dist(i,j)可能由三种情况转移而成:
    *   case1 :Dist(i-1,j-1),代表前i-1位和j-1位已经算好编辑距离,
    *       若w1[i]==w2[j],则Dist(i,j)==Dist(i-1,j-1);
    *       若w1[i]!=w2[j],只需要把w1[i]替换成w2[j],则Dist(i,j)==Dist(i-1,j-1)+1;
    *   case2 :Dist(i-1,j),代表前i-1位和j位已经算好编辑距离,
    *       只需要把w1[i]删除(因为w1的前i-1位和w2的前j位已经保证),则Dist(i,j)==Dist(i-1,j)+1;
    *   case3 :Dist(i,j-1),代表前i位和j-1位已经算好编辑距离
    *       只需要w2[j]插入到w1的i位(因为w1的前i位和w2的前j-1位已经保证),则Dist(i,j)==Dist(i,j-1)+1;
    *
    * 则有:minDist(i,j) = min(minDist(i-1,j-1)+(w1[i]==w2[j]?0:1), minDist(i,j-1)+1, minDist(i-1,j)+1);
    *
    * 当i=0, j=0,表示w1和w2都为"":
    *   minDist(0,0) = 0
    * 当i=1,2,3..., j=0,表示w2都为"":
    *   minDist(i,0) = i
    * 当i=0, j=1,2,3...,表示w1都为"":
    *   minDist(0,j) = j
    */
    public int minDistance (String word1, String word2) {

        int[][] recode = new int[word1.length()+1][word2.length()+1];
        for(int i=0; i<recode.length; i++) {
            for(int j=0; j<recode[0].length; j++) {
                if(i==0&&j>0) {
                    recode[i][j] = j;
                    continue;
                }
                if(i>0&&j==0) {
                    recode[i][j] = i;
                    continue;
                }
                if(i>0&&j>0) {
                    recode[i][j] = Math.min(Math.min(recode[i-1][j]+1, recode[i][j-1]+1),
                            recode[i-1][j-1]+(word1.charAt(i-1)==word2.charAt(j-1)?0:1));
                }

            }
        }
        return recode[word1.length()][word2.length()];
    }
}
发表于 2020-07-14 15:43:15 回复(0)
  java实现,运行时间:133ms占用内存:12688k。动态规划算法。
  像之前的背包问题、回文串分割问题,都需要一张二维表。设word1的第i个字母转换成word2的第j个字母需要的操作步骤数为dis[i][j],则有:如果word1.charAt[i-1]==word2.charAt[j-1],比如"abdce"中的"c"
和"fgc"中的"c",那么dis[4][3]=dis[3][2],即等于从"abd"转换成"fg"需要的操作步骤,因为相等的字母不涉及删除、添加、替换操作。而如果word1.charAt[i-1]!=word2.charAt[j-1]时,dis[ i ][ j ]=min(dis[ i-1 ][ j ],dis[ i ][ j-1 ],min[ i-1 ][ j-1 ])+1,在二维表中,当前的转换可由左边+添加操作、上边+删除操作、左上边+替换操作。所以是三者操作数中最小的,再加1。
  需要单独讨论的情况是当word1或者word2为空串时,步骤数为不为空的字符串的长度。
  代码如下:
public class Solution {
   public int minDistance(String word1, String word2) {
int length=word1.length()+1;
int width=word2.length()+1;
int [][]dis=new int[length][width];
for(int i=0;i<length;i++)
    dis[i][0]=i;
for(int j=0;j<width;j++)
    dis[0][j]=j;
if(length>1&&width>1)
{for(int m=1;m<length;m++)
{ for(int n=1;n<width;n++)
    {
        if(word1.charAt(m-1)==word2.charAt(n-1))
        {dis[m][n]=dis[m-1][n-1];}

        else{dis[m][n]=min(dis[m-1][n],dis[m][n-1],dis[m-1][n-1])+1;}

    }}}
    return  dis[length-1][width-1];}

public int min(int a,int b,int c)
{int min=Math.min(a,b);
min=Math.min(min,c);
return min; }
}



发表于 2019-08-18 18:40:47 回复(0)
public class Solution {
    public int minDistance(String word1, String word2) {
        int row = word1.length();
        int column = word2.length();
        int[][] distance = new int[row+1][column+1];
        for (int i = 0; i < column + 1; i++) distance[0][i] = i;
        for (int i = 0; i < row + 1; i++) distance[i][0] = i;
        for (int i = 1; i < row + 1; i++) {
            for (int j = 1; j < column + 1; j++) {
                if (word1.charAt(i-1) == word2.charAt(j-1)) {
                    distance[i][j] = distance[i-1][j-1];
                } else {
                    int temp = distance[i-1][j-1] < distance[i][j-1] ? distance[i-1][j-1] : distance[i][j-1];
                    int min = temp < distance[i-1][j] ? temp : distance[i-1][j];
                    distance[i][j] = min + 1;
                }
            }
        }
        return distance[row][column];
    }
}

编辑于 2017-06-05 10:13:15 回复(0)

Use f[i][j] to represent the shortest edit distance between word1[0,i) and word2[0, j). Then compare the last character of word1[0,i) and word2[0,j), which are c and d respectively (c == word1[i-1], d == word2[j-1]):

if c == d, then : f[i][j] = f[i-1][j-1]

Otherwise we can use three operations to convert word1 to word2:

(a) if we replaced c with d: f[i][j] = f[i-1][j-1] + 1;

(b) if we added d after c: f[i][j] = f[i][j-1] + 1;

(c) if we deleted c: f[i][j] = f[i-1][j] + 1;

Note that f[i][j] only depends on f[i-1][j-1], f[i-1][j] and f[i][j-1], therefore we can reduce the space to O(n) by using only the (i-1)th array and previous updated element(f[i][j-1]).

int minDistance(string word1, string word2) { int l1 = word1.size(); int l2 = word2.size(); vector<int> f(l2+1, 0); for (int j = 1; j <= l2; ++j)
            f[j] = j; for (int i = 1; i <= l1; ++i)
        { int prev = i; for (int j = 1; j <= l2; ++j)
            { int cur; if (word1[i-1] == word2[j-1]) {
                    cur = f[j-1];
                } else {
                    cur = min(min(f[j-1], prev), f[j]) + 1;
                }
    
                f[j-1] = prev;
                prev = cur;
            }
            f[l2] = prev;
        } return f[l2];
    
    }

Actually at first glance I thought this question was similar to Word Ladder and I tried to solve it using BFS(pretty stupid huh?). But in fact, the main difference is that there's a strict restriction on the intermediate words in Word Ladder problem, while there's no restriction in this problem. If we added some restriction on intermediate words for this question, I don't think this DP solution would still work.

发表于 2017-03-12 12:03:38 回复(0)
public class Solution {
    public int minDistance(String word1, String word2) {
        int[][] dp = new int[word1.length() + 1][word2.length() + 1];
        for (int i = 0; i < dp[0].length; i ++ ) dp[0][i] = i;
        for (int i = 0; i < dp.length; i ++ ) dp[i][0] = i;
        for (int i = 1; i < dp.length; i ++ ) {
            for (int j = 1; j < dp[0].length; j ++ ) {
                if(word1.charAt(i - 1) == word2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];
                else dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 1);
            }
        }
        return dp[word1.length()][word2.length()];
    }
}

发表于 2016-11-06 14:24:21 回复(0)