zoukankan      html  css  js  c++  java
  • 最短编辑距离

    题意

    给定两个字符串(A)(B),现在要将(A)经过若干操作变为(B),可进行的操作有:

    • 删除–将字符串A中的某个字符删除。
    • 插入–在字符串A的某个位置插入某个字符。
    • 替换–将字符串A中的某个字符替换为另一个字符。

    现在请你求出,将(A)变为(B)至少需要进行多少次操作。

    数据范围

    (1 leq |A|, |B| leq 1000)

    思路

    受最长公共子序列的启发,我们设(f(i, j))表示字符串(A[1 sim i])变为(B[1 sim j])需要进行多少次操作(下标从(1)开始)。

    考虑(A)的第(i)位和(B)的第(j)位,如果(A[i] = B[j]),那么(f(i, j) = f(i - 1, j - 1))

    如果(A[i] eq B[j]),考虑三种操作:

    • 如果进行删除操作,就是删除(A)的第(i)位,那么(f(i, j) = f(i - 1, j) + 1)
    • 如果进行插入操作,相当于对(B)进行删除操作,就是删除(B)的第(j)位,因此(f(i, j) = f(i, j - 1) + 1)
    • 如果进行替换操作,就是将(A)的第(i)位替换为(B)的第(j)位,因此(f(i, j) = f(i - 1, j - 1) + 1)

    将这三种情况取最小即可。

    下面考虑边界,考虑边界一般从遍历过程中用到的,但是之前没有初始化的值。这里就是(f(i, 0) = i, 1 leq i leq n)以及(f(0, i) = i, 1 leq i leq m)

    代码

    递推

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1010;
    
    int n, m;
    char a[N], b[N];
    int f[N][N];
    
    int main()
    {
        scanf("%d%s%d%s", &n, a + 1, &m, b + 1);
        for(int i = 1; i <= n; i ++) f[i][0] = i;
        for(int i = 1; i <= m; i ++) f[0][i] = i;
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m; j ++) {
                if(a[i] == b[j]) f[i][j] = f[i - 1][j - 1];
                else f[i][j] = min(f[i - 1][j], min(f[i][j - 1], f[i - 1][j - 1])) + 1;
            }
        }
        printf("%d
    ", f[n][m]);
        return 0;
    }
    

    记忆化搜索

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1010;
    
    int n, m;
    char a[N], b[N];
    int f[N][N];
    
    int dfs(int i, int j)
    {
        if(i == 0) return j;
        if(j == 0) return i;
        if(f[i][j] > 0) return f[i][j];
        if(a[i] == b[j]) f[i][j] = dfs(i - 1, j - 1);
        else f[i][j] = min(dfs(i - 1, j), min(dfs(i, j - 1), dfs(i - 1, j - 1))) + 1;
        return f[i][j];
    }
    
    int main()
    {
        scanf("%d%s%d%s", &n, a + 1, &m, b + 1);
        printf("%d
    ", dfs(n, m));
        return 0;
    }
    
  • 相关阅读:
    ubuntu16.04安装破解pycharm
    python解压,压缩,以及存数据库的相关操作
    cocoapods Error
    swift项目导入OC框架
    实现全屏滑动返回效果
    Storyboard & XIB 自己的理解
    View & Controller 一些方法的执行顺序
    Touch ID 实现
    Apple Pay 初探
    ReactiveCocoa学习
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14432605.html
Copyright © 2011-2022 走看看