算法 DAY56 动态规划12 583. 两个字符串的删除操作 72. 编辑距离

583. 两个字符串的删除操作

1、dp[i][j] 的定义
以i-1 结尾的word1 和 以 j-1结尾的word2想要达到相等,所需要删除元素的最少次数。

2、递推公式
如果 i-1 == j-1 那么dp[i][j] = dp[i-1][j-1]
如果 i-1 != j-1 那么dp[i][j]就会有三种选择
dp[i-1][j-1] + 2
dp[i-1][j] + 1
dp[i][j-1] + 1
其中 dp[i-1][j-1] + 2 和 dp[i][j - 1] + 1 是一样的,相当于在j-1的基础上i再退一步。
所以dp[i][j] = min(dp[i-1][j] + 1,dp[i][j-1] + 1)。

3.初始化
dp[i][0]:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。
dp[0][j]的话同理

4、遍历顺序显然是从上到下,从左到右

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1,0));
        for(int i = 0; i <= word1.size(); ++i) dp[i][0] = i;
        for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;

        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];
                else{
                    dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1);
                }
            }
        }
        return dp[word1.size()][word2.size()];
    }
};

72. 编辑距离

1. 确定dp数组(dp table)以及下标的含义

dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。

2. 确定递推公式

if (word1[i - 1] == word2[j - 1])
    不操作
if (word1[i - 1] != word2[j - 1])
    增
    删
    换

1、if (word1[i - 1] == word2[j - 1]) 那么说明不用任何编辑,dp[i][j] 就应该是 dp[i - 1][j - 1],即dp[i][j] = dp[i - 1][j - 1];

2、if (word1[i - 1] != word2[j - 1]),此时就需要编辑了

操作一:word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作。即 dp[i][j] = dp[i - 1][j] + 1;

操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作。即 dp[i][j] = dp[i][j - 1] + 1;

3、word2添加一个元素,相当于word1删除一个元素,
4、替换元素,word1替换word1[i - 1],使其与word2[j - 1]相同,此时不用增删加元素。那么只需要一次替换的操作,就可以让 word1[i - 1] 和 word2[j - 1] 相同。

所以 dp[i][j] = dp[i - 1][j - 1] + 1;

综上,当 if (word1[i - 1] != word2[j - 1]) 时取最小的,即:dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;

3. dp数组如何初始化
再回顾一下dp[i][j]的定义:

dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。

那么dp[i][0] 和 dp[0][j] 表示什么呢?

dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]。

那么dp[i][0]就应该是i,对word1里的元素全部做删除操作,即:dp[i][0] = i;

同理dp[0][j] = j;

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1,0));
        for(int i = 0; i <= word1.size();++i) dp[i][0] = i;
        for(int j = 0; j <= word2.size();++j) dp[0][j] = j;
        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];
                else{
                    dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]})+1;
                }
            }

        }
        return dp[word1.size()][word2.size()];
    }
};

你可能感兴趣的:(算法,动态规划,c++)