【ACWing】902. 最短编辑距离

题目地址:

https://www.acwing.com/problem/content/904/

给定两个字符串 A A A B B B,允许对 A A A进行三种操作:
1、将其中某个字符删除;
2、在任意位置添加某个字符;
3、将任意一个字符修改为另一个字符。
问将 A A A变为 B B B至少需要多少次操作。

数据范围:
1 ≤ n , m ≤ 1000 1\le n,m\le 1000 1n,m1000

思路是动态规划。设 f [ i ] [ j ] f[i][j] f[i][j] A A A的前 i i i个字符组成的子串最少经过多少次操作可以变成 B B B的前 j j j个字符组成的子串。根据对 A A A的末尾进行的最后一次操作类型来分类。如果是删除,那么就是要将 A A A的长 i − 1 i-1 i1前缀变成 B B B的前 j j j个字符,再加上删除 B B B这个操作,总最小次数是 f [ i − 1 ] [ j ] + 1 f[i-1][j]+1 f[i1][j]+1;如果是添加,那么就是要将 A A A的长 i i i前缀变成 B B B的前 j − 1 j-1 j1个字符,再加上在 A A A末尾添加 B B B末尾这个操作,总最小次数是 f [ i ] [ j − 1 ] + 1 f[i][j-1]+1 f[i][j1]+1;如果是修改,分两种情况,如果 A [ i − 1 ] ≠ B [ j − 1 ] A[i-1]\ne B[j-1] A[i1]=B[j1],那么必须做修改,就是要将 A A A的长 i − 1 i-1 i1前缀变成 B B B的前 j − 1 j-1 j1个字符,再加上末尾修改这个操作,总最小次数是 f [ i − 1 ] [ j − 1 ] + 1 f[i-1][j-1]+1 f[i1][j1]+1;如果 A [ i − 1 ] = B [ j − 1 ] A[i-1]= B[j-1] A[i1]=B[j1],则不必修改,将 A A A的长 i − 1 i-1 i1前缀变成 B B B的前 j − 1 j-1 j1个字符即可,总最小次数是 f [ i − 1 ] [ j − 1 ] f[i-1][j-1] f[i1][j1] f [ i ] [ j ] f[i][j] f[i][j]在上面几个情况里取最小即可。代码如下:

#include <iostream>
using namespace std;

const int N = 1010;
int n, m;
string a, b;
int f[N][N];

int main() {
    
    
    cin >> n >> a;
    cin >> m >> b;

    for (int i = 0; i <= m; i++) f[0][i] = i;
    for (int i = 0; i <= n; i++) f[i][0] = i;

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
    
    
            f[i][j] = min(f[i - 1][j] + 1, f[i][j - 1] + 1);
            if (a[i - 1] == b[j - 1]) f[i][j] = min(f[i][j], f[i - 1][j - 1]);
            else f[i][j] = min(f[i][j], f[i - 1][j - 1] + 1);
        }

    cout << f[n][m] << endl;

    return 0;
}

时空复杂度 O ( n m ) O(nm) O(nm)

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/114023750
今日推荐