首页 > 试题广场 >

编辑距离

[编程题]编辑距离
  • 热度指数: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 {
    /**
    * 题目解析:
    * 1. 本题涉及动态规划 - Dynamic Programming
    * 之所以翻译成动态规划,是因为发明者是数学家,Programming不是CS中的编程,应该理解为规划或计划
    *    该解释参考自算法设计与分析基础》
    * 2. 给定两个单词word1和word2,需要将word1转换为word2
    *    转换的条件是只能执行:插入一个字符,删除一个字符,替换一个字符
    *    这三种操作,没执行一次,算一步,求word1转换为word2所需最小步数
    *
    * 解题思路:
    * 1. 动态规划解题思路为: 拆分为子问题 - 找出递归式
    * 2. 动态规划 需要用最优解来填充一张表 - 可能是一维表 or 二维表
    * 
    * 问题举例理解: “ab” 到 “abc” 的最小步数
    * 所有子问题:
    * 0. "" 到 "a"【及  到 "ab" 及 到 "abc"】的最优解
    * 1. "a" 到 "a" 【及  到 "ab" 及 到 "abc"】的最优解
    * 2. "ab" 到 "a" 【及  到 "ab" 及 到 "abc"】的最优解
    * 用这些最优解填充一张二维表 表的右下角为 整个问题的"ab" 到 "abc"的最优解
    * 二维表:#代表空字符串
    * 0 # a b c
    * # 0 1 2 3
    * a 1 0 1 2
    * b 2 1 0 1
    * 由表可知 由"ab" 到 "abc" 最优解:只需进行一步
    * 
    * 递推公式:
    * F(i,j) 代表word1的前i -1个字符组成的字符串到 word2的前j -1个字符组成的字符串的最优解
    * 例:F(2, 3) 代表word1的前1个字符组成的字符串到 word2的前2个字符组成的字符串的最优解
    * 若 i == j,则意为着不需额外操作,则F(i,j) 显然 等于 F(i - 1,j - 1)
    * 若 i != j,则肯定需要1步操作来转换
    * 以 "ab" 到 "abc"为例,该最优解为: min{"a" 到 "abc"的最优解, "ab" 到 "ab"的最优解,"a" 到 "ab" 的最优解 } + 1
    * 所以 该情况递推公式为:F(i,j) = min{F(i - 1, j), F(i, j - 1),F(i - 1, j - 1) } + 1
    *
    */
    public int minDistance(String word1, String word2) {
        // 获取字符串长度 以便建立二维表
        int len1 = word1.length();
        int len2 = word2.length();

        // 建立dp表
        int[][] dp = new int[len1 + 1][len2 + 1];

        // 初始化表

        // 第一行为 空字符串 到 对应字符串 所需 转换步数
        for (int i = 0; i <= len2; i++) {
            dp[0][i] = i;
        }
        // 第一列为 空字符串 到 对应字符串 所需 转换步数
        for (int i = 0; i <= len1; i++) {
            dp[i][0] = i;
        }

        // 比较 字符 填充dp表其余部分
        // 跳过第一行第一列:因为已经初始化填充了
        for (int i = 1; i <= len1; i++) { // word1
            for (int j = 1; j <= len2; j++) { // word2
                // i 索引对应值== j 索引对应值,F(i, j ) = F(i - 1, j - 1)
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    // 其他情况
                    // 取min{F(i - 1, j - 1) F(i - 1, j) F(i, j - 1) } + 1
                    int temp = Math.min(dp[i - 1][j] , dp[i][j - 1]);
                    dp[i][j] = Math.min(temp, dp[i - 1][j - 1]) + 1;
                }
            }
        }

        return dp[len1][len2];
    }
}

发表于 2018-10-11 17:27:38 回复(4)
public class Solution {
    public int minDistance(String word1, String word2) {
        if(word1 == null && word2 == null)
        	return 0;
        if(word1 == null)
        	return word2.length();
        if(word2 == null)
        	return word1.length();
        
        // dp[i][j]代表由word1的前i个子串变为word2的前j个子串的花费
        // 其中i,j均可为0,代表空串:""
        int[][] dp = new int[word1.length() + 1][word2.length() + 2];
        dp[0][0] = 0;
        // 首先初始化两个子串中有一个为空串的情况
        for(int i = 1; i <= word1.length(); i++){
        	dp[i][0] = i;
        }
        for(int j = 1; j <= word2.length(); j++){
        	dp[0][j] = j;
        }
        
        for(int i = 1; i <= word1.length(); i++){
        	for(int j = 1; j <= word2.length(); j++){
        		// 如果这两个字符相等,那么交由上一种情况处理,如abc,dfc
        		// 这种情况与ab,df花费是一样的
        		// 不然就要在删除,插入,修改中取花费最小的那个
        		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], dp[i][j-1]), dp[i-1][j-1]) + 1;
            }
        }
        return dp[word1.length()][word2.length()];
    }
}

发表于 2017-05-08 14:25:54 回复(3)
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)
class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.length();
        int n = word2.length();
        vector<vector<int> > dp(m+1,vector<int>(n+1,0));
        for(int i=1;i<=m;i++)
        	dp[i][0] = i;
        for(int j=1;j<=n;j++)
        	dp[0][j] = j;
        for(int i=1;i<=m;i++)
        	for(int j=1;j<=n;j++)
        	{
        		if(word1[i-1] == word2[j-1])
        			dp[i][j] = dp[i-1][j-1];
        		else
        			dp[i][j] = min(dp[i-1][j]+1, min(dp[i][j-1]+1, dp[i-1][j-1]+1));
			}
    	return dp[m][n];
	}
};

发表于 2017-08-26 03:16:44 回复(0)
/*
找递归函数:

这个案例的子问题是什么呢?考虑寻找的他们的前缀子串的编辑距离,让我们表示他们为

[1 ... i]和[1 ....j] , 1<i<m 和1 <j <n

显然,这是解决最终问题的子问题,记为E(i,j)。我们的目标是找到E(m,n)和最小的编辑距离。

我们可以用三种方式: (i, -), (-, j) 和(i, j)右对齐两个前缀字符串。连字符符号( – )表示没有字符。看一个例子或许会更清楚:

假设给定的字符串是 SUNDAY 和 SATURDAY。如果 i= 2 ,  j = 4,即前缀字符串分别是SU和SATU(假定字符串索引从1开始)。这两个字串最右边的字符可以用三种不同的方式对齐:

1  (i, j): 对齐字符U和U。他们是相等的,没有修改的必要。我们仍然留下其中i = 1和j = 3,即问题E(1,3)

2 (i, -) : 对第一个字符串右对齐,第二字符串最右为空字符。我们需要一个删除(D)操作。我们还留下其中i = 1和j = 4的 子问题 E(i-1,j)。

3 (-, j)  :  对第二个字符串右对齐,第一个字符串最右为空字符。在这里,我们需要一个插入(I)操作。我们还留下了子问题 i= 2 和 j = 3,E(i,j-1)。

对于这三种操作,我可以得到最少的操作为:

E(i, j) = min( [E(i-1, j) + D], [E(i, j-1) + I],  [E(i-1, j-1) + R (如果 i,j 字符不一样)] )

到这里还没有做完。什么将是基本情况?

当两个字符串的大小为0,其操作距离为0。当其中一个字符串的长度是零,需要的操作距离就是另一个字符串的长度. 即:

E(0,0)= 0,E(i,0)= i,E(0,j)= j

为基本情况。这样就可以完成程序了。
*/
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main()
{
string str1,str2;
while(cin>>str1>>str2)
{
int len1=str1.length();
int len2=str2.length();
if(len1<=0 && len2<=0)
return 0;
vector< vector<int> >result(len1+1 , vector<int>(len2+1,0));

for(int i=0;i<=len1;++i)
result[i][0]=i;
for(int j=0;j<=len2;++j)
result[0][j]=j;

for(int i=1;i<=len1;++i)
{
for(int j=1;j<=len2;++j)
{
int min=result[i-1][j-1];
if(str1[i-1]!=str2[j-1])  //这个库如果是str1[i],str2[j]会有溢出,i-1代表的就是第i的子串。
min++;
min=min<result[i-1][j]+1 ? min : result[i-1][j]+1;
min=min<result[i][j-1]+1 ? min : result[i][j-1]+1;
result[i][j]=min;
}
}
cout<<result[len1][len2]<<endl;
}

return 0;
}
编辑于 2016-10-17 16:41:54 回复(0)
class Solution {
public:
    int minDistance(string word1, string word2) {
        //return dfs(word1, word2, 0);
        // 非递归动态规划法:
        // word2 = [a, b, d], word1 = [a, b]
        // 则假设我们已经求出了word1的[0,0]位置的最小操作,那么当新增一个字符b时,有如下的计算匹配:
        // 第一轮:令i = 1, j = 0, 使word1[i]依次匹配word2的[0, 2]位置的字符
        //    [a, b, c]
        // [a, b]
        // 则此时的计算结果就为  dp[1][0] = 1(删除word1中的a字符) + 1(替换单词b)
        // 第二轮:令i = 1, j = 1, 使word1[i]依次匹配word2的[1, 2]位置的字符
        //   [a, b, c]
        //   [a, b]
        // 则此时的计算结果为dp[1][1] = dp[0][0] + 0(b字符已经相同无须变换)
        // 第三轮:令i = 1, j = 2,使word1[i]依次匹配word2的[2, 2]位置的字符
        //   [a, b, c]
        //      [a, b]
        // 刚此时的计算结果为dp[1][2] = dp[0][1] + 1(替换单词b),
        // 但还需要跟上一轮的结果作比较,因为此时的结果有可能小于在上一轮匹配位置之后,直接插入第j个字符后的结果,
        // dp[1][2] = min(dp[1][2], dp[1][1] + 1)
        // 或是小于没有添加当前字符时的匹配结果
        // dp[1][2] = min(dp[1][2], dp[0][2] + 1)
        // 最终得到一张二维表:
        //   #  ""  a  b  c
        //   "" 0   1  2  3
        //   a  1   0  1  2
        //   b  2   2  0  1
        // 基本的流程就如上所示,但还需要确认一下初始条件和边界条件
        // 初始条件:
        //   y轴为word1,x轴为word2,由于在比较的过程中需要统计删除word1的前[0, i]字符的步数,因为在横纵坐标的
        //   初始位置添加空的字符串便于计算
        // 边界条件:
        //   word1.length() == 0 || word2.length() == 0
        //
        int w1 = word1.length(), w2 = word2.length();
        if (w1 == 0) return w2;
        if (w2 == 0) return w1;
        int dp[w1+1][w2+1];
        for (int i = 0; i <= w1; i++) dp[i][0] = i;
        for (int i = 0; i <= w2; i++) dp[0][i] = i;
        for (int i = 1; i <= w1; i++) {
            for (int j = 1; j <= w2; j++) {
                int cur_steps = dp[i-1][j-1] + (word1[i-1] != word2[j-1]); // 替换操作
                dp[i][j] = min(cur_steps, dp[i][j-1] + 1);                 // 插入操作
                dp[i][j] = min(dp[i][j], dp[i-1][j] + 1);                  // 删除操作
            }
        }
        return dp[w1][w2];
    }

发表于 2020-04-15 21:16:29 回复(0)
    /**
     * 核心的递归算法,只要搞清楚插入操作和删除操作时,索引怎么变即可
     * @param word1
     * @param word2
     * @return
     */
    public int minDistance(String word1, String word2) {
        return Core(word1, word2, 0, 0);
    }

    private int Core(String word1, String word2, int index1, int index2) {
        if (index1 == word1.length() && index2 == word2.length())
            return 0;
        if (index1 >= word1.length() && index2 < word2.length())
            return word2.length() - index2;
        if (index2 >= word2.length() && index1 < word1.length())
            return word1.length() - index1;
        if (word1.charAt(index1) == word2.charAt(index2))
            return Core(word1, word2, index1 + 1, index2 + 1); // 当前位置字符相等时我们认为距离不会增加
        else {
            return Math.min(Math.min(Core(word1, word2, index1, index2 + 1),// 插入操作
                    Core(word1, word2, index1 + 1, index2)),// 删除操作
                    Core(word1, word2, index1 + 1, index2 + 1)) + 1;// 替换操作
        }
    }

    /**
     * 改动态规划,变化的量就两个,index1和index2,不变量就是word1和word2
     * 所以index1和index2的范围即为动态规划数组的大小范围;
     * 接下来看递归的终止条件  终止条件是两种情况:1)当index1和index2同时到了字符串末尾
     *                             2)当index1和index2其中之一到了字符串末尾
     * 填数组基础信息就看上面两个条件;
     * 再者是依赖关系的寻找:   根据看word1.charAt(index1)是否等于word2.charAt(index2)分为两种情况:
     *                                1)当前位置字符相等时我们认为距离不会增加 dp[i][j] = dp[i+1][j+1];
     *                                2)当前位置字符不相等时我们认为距离会增加一,通过三种方式增加,看哪种方式增加之后的距离更小
     *                                     dp[i][j] = min(dp[i][j+1],dp[i+1][j],dp[i+1][j+1]);
     * @param word1
     * @param word2
     * @return
     */
    public int minDistance_dp(String word1, String word2) {
        int dp[][] = new int[word1.length() + 1][word2.length() + 1];
        dp[word1.length()][word2.length()] = 0;
        for (int row = 0; row < word1.length(); row++) {
            dp[row][word2.length()] = word1.length() - row;
        }
        for (int column = 0; column < word2.length(); column++) {
            dp[word1.length()][column] = word2.length() - column;
        }
        for (int row = word1.length() - 1; row >= 0; row--) {
            for (int column = word2.length() - 1; column >= 0; column--) {
                if (word1.charAt(row) == word2.charAt(column))
                    dp[row][column] = dp[row + 1][column + 1];
                else {
                    dp[row][column] = Math.min(
                            Math.min(dp[row + 1][column], dp[row][column + 1]),
                            dp[row+1][column+1])+1;
                }
            }
        }
        return dp[0][0];
    }
发表于 2018-07-06 22:28:02 回复(2)
记忆化搜索
public class Solution {
    public int maxValue=1000000000;
    public int search (int [][]f,String word1, String word2,int x,int y){
        if(x > word1.length() || y >word2.length()){
            return maxValue;
        }
        if(x == word1.length()  && y == word2.length()){
            return 0;
        }
        if(f[x][y]>0){
            return  f[x][y];
        }
        if(x<word1.length()&& y<word2.length()&& word1.charAt(x) == word2.charAt(y)){
            return f[x][y] = search(f,word1,word2,x+1,y+1);
        }else {
            return f[x][y] = Math.min(search(f,word1,word2,x,y+1),Math.min(search(f,word1,word2,x+1,y),search(f,word1,word2,x+1,y+1)))+1;
        }
    }
    public  int minDistance(String word1, String word2) {
        if(word1==null || word2 == null) return 0;
        if(word1.length() ==0 && word2.length()==0) return 0;
        if(word1.length() ==0 ) return word2.length();
        if(word2.length() ==0 ) return word1.length();
        int f[][] = new int [word1.length()+1][word2.length()+1];
        return search(f,word1,word2,0,0);
    }
}

发表于 2017-06-10 00:17:25 回复(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)

对应三种字符操作方式:

edit[i-1][j]+1相当于给word2的最后插入了word1的最后的字符,插入操作使得edit+1,之后计算edit[i-1][j]

edit[i][j-1]+1相当于将word2的最后字符删除,删除操作edit+1,之后计算edit[i][j-1];

edit[i-1][j-1]+flag相当于通过将word2的最后一个字符替换为word1的最后一个字符。flag标记替换的有效次数。

发表于 2020-04-28 11:47:38 回复(0)
//动态规划ok
class Solution {
public:    
    int minDistance(string word1, string word2) 
    {
        int l1=word1.length();
        int l2=word2.length();
        if (l1 == 0 || l2 == 0)
            return max(l1, l2);
        vector<vector<int>> co(l1+1,vector(l2+1,INT_MAX));
        for(int i=0;i<=l1;i++)        
            co[i][0]=i;
        for(int j=0;j<=l2;j++)
            co[0][j]=j;
        for(int i=1;i<=l1;i++)
        {
            for(int j=1;j<=l2;j++)
            {
                co[i][j]=co[i-1][j-1]+1; //replace
                if(word1[i-1]==word2[j-1])
                    co[i][j]--;   //don't need replacement
                co[i][j]=min(co[i][j],co[i][j-1]+1);  //delete
                co[i][j]=min(co[i][j],co[i-1][j]+1);  //insert
            }
        }
        return co[l1][l2];
    }
};
//超时递归
class Solution {
public:
    int mini;
    void core(string w1,string w2,int idx1,int idx2,int l1,int l2,int cnt)
    {
        if(cnt>mini)
            return;
        if(idx1>=l1||idx2>=l2)
        {
            if(idx2<l2)
                cnt+=l2-idx2;
            else if(idx1<l1)
                cnt+=l1-idx1;
            mini=min(mini,cnt);
            return;
        }        
        if(w1[idx1]==w2[idx2])
            core(w1,w2,idx1+1,idx2+1,l1,l2,cnt);           
        else
            core(w1,w2,idx1+1,idx2+1,l1,l2,cnt+1);//replace
        core(w1,w2,idx1,idx2+1,l1,l2,cnt+1);//insert
        core(w1,w2,idx1+1,idx2,l1,l2,cnt+1);//delete
    }
    int minDistance(string word1, string word2) 
    {
        int l1=word1.length();
        int l2=word2.length();
        if(l1==0||l2==0)
            return max(l1,l2);
        mini=INT_MAX;
        core(word1,word2,0,0,l1,l2,0);
        return mini;
    }
};
编辑于 2018-07-07 08:10:09 回复(0)
class Solution {
public:
    int minDistance(string word1, string word2) {
    int len1 = word1.size();
    int len2 = word2.size(); 
    vector<vector<int>> d(len1+1, vector<int>(len2+1,0));  //动态给二维容器赋初值
    for (int i = 0; i <= len1; i++) {
        d[i][0] = i;
    }
    for (int j = 0; j <= len2; j++) {
        d[0][j] = j;
    }
    for (int i = 1; i <= len1; i++) {
        for (int j = 1; j <= len2; j++) {
            // 算法中 a, b 字符串下标从 1 开始,c++从 0 开始,所以 -1
            if (word1[i-1] == word2[j-1]) {
                d[i][j] = d[i-1][j-1];
            } else {
                d[i][j] = min(min(d[i-1][j]+1, d[i][j-1]+1), d[i-1][j-1]+1);
            }
        }
    }
    return d[len1][len2];
}      
};
发表于 2018-05-02 11:56:50 回复(0)
这道题就是一道动态规划的题。动态规划的题目主要有二个特点:1.最优子结构;2.重叠子问题。
假如,word1={c1c2c3......cn},word2={s1s2s3s4.......sm};c,s都是字符,当c1=c2时,这是不需要操作,这个最小的操作数,word1-c1和word2-s1的最小操作数,如果c1!=s1时,则我们可以有三种操作:1.删除,此时,word1-c1和word2之间的,2.插入:word1,word2-s1,3.替换,此时word1-c1与word2-s1之间的。代码如下:
class Solution {
public:
inline int min(const int a,const int b,const int c)
{
    if(a<b&&a<c) return a;
    else if(b<a&&b<c) return b;
    else return c;
}
int minDistance(string word1, string word2) {
    int n1=word1.size(),n2=word2.size();
    if(n1==0) return n2;
    if(n2==0) return n1;
    int dp[n1+1][n2+1];
    for(int i=0;i<n1+1;i++)
    {
        dp[i][0]=i;
    }            
    for(int i=0;i<n2+1;i++)
    {
        dp[0][i]=i;
    }
    for(int i=0;i<n1;i++)
    {
        for(int j=0;j<n2;j++)
        {
            if(word1[i]==word2[j])
                dp[i+1][j+1]=dp[i][j];
            else{
                dp[i+1][j+1]=min(dp[i][j+1],dp[i+1][j],dp[i][j])+1;
            }    
        }
    }
    return dp[n1][n2];
}
};

发表于 2018-04-18 18:36:47 回复(0)
public class Solution {
    public int minDistance(String word1, String word2) {
        char[] chs = word1.toCharArray() ; 
        char[] cht = word2.toCharArray() ; 
        int n = chs.length ; 
        int m = cht.length ;
        if(n == 0 || m == 0){
            return Math.abs(n-m) ; 
        }
        int[][] dp = new int[chs.length][cht.length] ; 
        for(int i = 0;i < n;i++){
            for(int j = 0;j < m;j++){
                dp[i][j] = n+m ; 
            }
        }
        boolean flag = false ; 
        for(int i = 0;i < n;i++){
            if(chs[i] == cht[0]){
                flag = true ; 
            }
            dp[i][0] = flag ? i:i+1 ; 
        }
        flag = false ; 
        for(int j = 0;j < m;j++){
            if(chs[0] == cht[j]){
                flag = true ; 
            }
            dp[0][j] = flag ? j:j+1 ; 
        }
        for(int i = 1;i < n;i++){
            for(int j = 1;j < m;j++){
                int num = chs[i] == cht[j] ? 0 : 1 ; 
                dp[i][j] = Math.min(dp[i-1][j]+1,dp[i][j]) ; 
                dp[i][j] = Math.min(dp[i][j-1]+1,dp[i][j]) ; 
                dp[i][j] = Math.min(dp[i-1][j-1]+num,dp[i][j]) ; 
            }
        }
        return dp[n-1][m-1] ; 
    }
}

发表于 2018-03-02 10:20:59 回复(0)
class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1=word1.size(),len2=word2.size();
        vector<vector<int>> dp(len1+1,vector<int>(len2+1));
        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){
                dp[i][j]=min(min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+(word1[i-1]==word2[j-1]?0:1));
            }
        }
        return dp[len1][len2];
    }
};

发表于 2017-09-07 15:43:55 回复(0)
public int minDistance(String word1, String word2) {
		if (word1 == null || word2 == null)
			return 0;
		int[][] res = new int[word1.length() + 1][word2.length() + 1];
		for (int i = 0; i <= word1.length(); i++) {
			res[i][0] = i;
		}
		for (int j = 0; j <= word2.length(); j++) {
			res[0][j] = j;
		}

		for (int i = 0; i < word1.length(); i++) {
			for (int j = 0; j < word2.length(); j++) {
				if (word1.charAt(i) == word2.charAt(j))
					res[i + 1][j + 1] = res[i][j];
				else {
					res[i + 1][j + 1] = 1 + min(res[i + 1][j], res[i][j + 1], res[i][j]);
				}
			}
		}

		return res[word1.length()][word2.length()];
	}

	private int min(int i, int j, int k) {
		int min = Math.min(i, j);
		min = Math.min(min, k);
		return min;
	}

发表于 2017-07-08 11:44:21 回复(0)

如果 a[1] === b[1],那么 d[1][1] 等于 d[0][0],也就是 0;
如果 a[1] !== b[1],那么 d[1][1] 等于 d[0][1]、d[1][0] 和 d[0][0] 三者中的最小值 + 1,也就是 1。
接着用同样的方式,可以求得 d[1][2]、d[1][3]、……、d[1][n],然后继续求得 d[2][1]、d[2][2]、……、d[2][n],一直到 d[m][n]。代码实现如下:
int minDistance(string word1, string word2) {
    int l1 = word1.size(), l2 = word2.size();
    if(l1 == 0) return l2;
    if(l2 == 0) return l1;
    vector<vector<int>> dp(l1+1, vector<int>(l2+1, 0));
    
    for(int i = 0; i <= l1; ++i)
        dp[i][0] = i;
    for(int j = 0; j <= l2; ++j)
        dp[0][j] = j;
    
    for(int m = 1; m <= l1; ++m){
        for(int n = 1; n <= l2; ++n){
            if(word1[m-1] == word2[n-1])
                dp[m][n] = dp[m-1][n-1];
            else{
                int min1 = min(dp[m-1][n]+1, dp[m][n-1]+1);
                dp[m][n] = min(min1, dp[m-1][n-1]+1);
            }
        }
    }
    return dp[l1][l2];
}

发表于 2019-05-15 15:44:03 回复(0)
class Solution {
public:
    
    // dp[i][j]代表由word1的前i个子串变为word2的前j个子串的花费
   int minDistance(string word1, string word2)
    {
      int m = word1.length(),n =  word2.length();
      vector<vector<int> > dp(m+1,vector<int>(n+1,0));
      for(int i=1;i<=m;i++)
         dp[i][0] = i; /// delete i chars of word1
      for(int j=1;j<=n;j++)
         dp[0][j] = j;  /// insert j chars of word2
       for(int i=1;i<=m;i++)
       {
           for(int j=1;j<=n;j++)
            {
                if(word1[i-1] == word2[j-1])
                    dp[i][j] = dp[i-1][j-1];
                else
                    dp[i][j] = min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+1)); /// delete,insert,replace
            }
       }
       return dp[m][n];
    }
};

发表于 2017-07-11 15:25:20 回复(0)
class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.size();
        int n = word2.size();
        vector<vector<int> >dp(m+1,vector<int>(n+1));
        for(int i = 0;i <= m ;i++){
            for(int j = 0; j <= n ;j++){
                if(i ==0){
                    dp[i][j] = j;
                }
                else if(j ==0){
                    dp[i][j] = i;
                }
                else{
                    dp[i][j] = min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+(word1[i-1]==word2[j-1]?0:1)));
                }
            }
        }
        return dp[m][n];
    }
};

发表于 2017-01-09 17:03:17 回复(0)
    int minDistance(string word1, string word2) {
        // write code here
        int m = word1.length();
        int n = word2.length();
        vector<vector<int>> dp(m+1,vector<int>(n+1));
        //设置边界
        for(int i=1;i<=m;++i)dp[i][0]=i;
        for(int i=1;i<=n;++i)dp[0][i]=i;
        for(int i=1;i<=m;++i)
        {
            for(int j=1;j<=n;++j)
            {
                int n = 1;
                if(word1[i-1]==word2[j-1])
                    n = 0;
                dp[i][j] = min(dp[i-1][j-1]+n,min(dp[i-1][j],dp[i][j-1])+1);
            }
        }
        return dp[m][n];
    }
};

发表于 2022-01-05 16:43:48 回复(0)