题解 | 编辑距离

alt

题干解析

题设给予我们两个字符串,我们每次能够对第一个字符串进行任意次以下操作之一:

  • 删除一个字符
  • 插入一个字符
  • 更改一个字符 求将第一个字符串更改为第二个字符串的最少操作次数。

算法思路

设第一个字符串为s1,第二个为s2

我们定义二维状态数组dp[i][j]表示将s1的前i个字符字串更改为s2的前j个字符字串的最少操作次数。

不难得出如果针对s1[i]==s2[j]时,dp[i][j]=dp[i-1][j-1],也就是说无需再进行操作,直接继承。

反之如果不成立,需要在原基础上进行一次操作:

  • 删除一个字符操作:dp[i][j] = dp[i-1][j] + 1
  • 插入一个字符操作:dp[i][j] = dp[i][j-1] + 1
  • 更改一个字符操作:dp[i][j] = dp[i-1][j-1] + 1 三种操作取其总计操作数最小的一个即可。

由此状态转移方程如下:

实现代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    string s1, s2;
    cin >> s1 >> s2;
    vector<vector<int>> dp(s1.size() + 1, vector<int>(s2.size() + 1, 0));
    for (int i = 0; i <= s1.size(); ++i) {
        for (int j = 0; j <= s2.size(); ++j) {
            if (i > 0 && j > 0 && s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1];
            else {
                if (!i && !j) continue;
                int min_ = INT_MAX;
                if (i > 0) min_ = min(min_, dp[i - 1][j]);
                if (j > 0) min_ = min(min_, dp[i][j - 1]);
                if (i > 0 && j > 0) min_ = min(min_, dp[i - 1][j - 1]);
                dp[i][j] = min_ + 1;
            }
        }
    }
    cout << dp[s1.size()][s2.size()];

    return 0;
}

复杂度分析

  • 时间复杂度:,其中n为s1的长度,m为s2的长度,下同
  • 空间复杂度:
全部评论

相关推荐

昨天 01:39
南昌大学 Java
重剑Ds:感觉不太可能 后端都减飞了 根本不缺人
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务