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

    题目传送门

    一、解题思路

    \(LCS\)(最长公共子序列)问题的状态表示是很接近的。

    QQ截图20210315105007.png

    (1)集合划分

    \(f[i,j]\)含义:\(a[1..i]\)变成\(b[1..j]\)的操作步数。

    动态规划,就是不断的进行状态转移,并在转移过程中进行判断。因为要求是:两个字符串的最短编辑距离,我们不知道最短编辑距离是多少,就希望知道最终的状态是从哪些状态转移过来,前面的状态可以通过增加、删除、修改转移过来。如果我们能从小到大,将每个可能的状态描述出来,就不怕迁移了~

    如何描述每个状态呢?当然是讨论\(a,b\)字符串的每一个子串,每一个子串的编辑距离可以算出来的话,那么最终的编辑距离肯定也就出来了。

    (2)属性

    操作数的最小值,\(min\)

    (3)状态计算

    按题意划分为删除,增加,修改三种情况

    一、删除
    如果\(a[i]\)通过删除操作,可以达到\(b[j]\)一样的状态,那么最后的一步去掉第\(i\)个字符,也就是说\(a[i-1]\)之前的字符串可以通过\(f[i-1][j]\)步可以转化为\(b[j]\),那么加上删除的动作,就是:\(f[i][j]=f[i-1][j]+1\)

    二、增加
    如果\(a[i]\)通过增加操作,可以达到\(b[j]\)一样的状态,那么就意味着在\(a[i]\)通过\(f[i][j-1]\)步达到\(b[j-1]\)状态。也就是:\(f[i][j]=f[i][j-1]+1\)

    三、修改

    如果\(a[i]=b[j]\)是不需要进行修改的,就是\(f[i,j]=f[i-1,j-1]\)
    如果\(a[i]!=b[j]\)是需要进行修改的,就是\(f[i,j]=f[i-1,j-1]+1\)

    四、综合

    \(f[i][j] = min(f[i-1][j]+1,f[i][j-1]+1,f[i-1][j-1]+(a[i] == b[j]?0:1))\);

    五、初始化

    细节问题:初始化怎么搞

    先考虑有哪些初始化嘛

    1.你看看在\(for\)遍历的时候需要用到的但是你事先没有的,(往往就是什么\(0\)\(1\)啊之类的)就要预处理

    2.如果要找\(min\)的话别忘了\(INF\),要找有负数的max的话别忘了\(-INF\)

    \(ok\),对应的:

    1. \(f[0][i]\):如果\(a\)初始长度就是\(0\),那么只能用插入操作让它变成\(b\)

      \(f[i][0]\)同样地,如果\(b\)的长度是\(0\),那么\(a\)只能用删除操作让它变成\(b\)

    2. \(f[i][j]\) = \(INF\) 虽说这里没有用到,但是把考虑到的边界都写上还是保险

    二、实现代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1010;
    int n, m;
    char a[N], b[N];
    int f[N][N];
    
    // 最短编辑距离
    int main() {
        //优化输入
        ios::sync_with_stdio(false);
        cin >> n >> (a + 1) >> m >> (b + 1);
    
        //这个初始化牛X啊!
        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] == b[j]) 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);
            }
    
        printf("%d\n", f[n][m]);
        return 0;
    }
    
  • 相关阅读:
    vsftpd下错误之:500 OOPS
    material mem
    如何查看core文件
    java 开发工具使用
    Java计算几何图形的面积
    Java实现经理与员工的差异
    Java适配器模式的简单应用
    Java实现策略模式的简单应用
    Java单例模式的应用
    Java求解汉诺塔问题
  • 原文地址:https://www.cnblogs.com/littlehb/p/15431771.html
Copyright © 2011-2022 走看看