ACwing 902 - 最短编辑距离(最长上升子序列模型)

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

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

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

输入格式

第一行包含整数n,表示字符串A的长度。

第二行包含一个长度为n的字符串A。

第三行包含整数m,表示字符串B的长度。

第四行包含一个长度为m的字符串B。

字符串中均只包含大写字母。

输出格式

输出一个整数,表示最少操作次数。

数据范围

1 ≤ n,m ≤ 1000

输入样例:

10
AGTCTGACGC
11
AGTAAGTAGGC

输出样例:

4

题目大意:

给出两个字符串的长度和两个字符串AB,可以对串A进行三种操作:增、删、改,输出串A到串B至少需要几次操作。

解题思路:

线性dp问题,dp问题从两方面考虑

  • 状态表示: 用两维去表示状态,f(i, j) 表示字符串 A 的前 i 个字符变化到字符串 B 的前 j 个字符所需的操作数, 本题要求的是最小值,所以f[i][j] 表示为A串的前 i 个字符变化到 B串的前 j 个字符所需的最小操作数。
  • 状态计算: 考虑怎么转移到f[i][j],有增,删,改三种操作,考虑增加,即考虑f[i][j - 1] 串A的前 i 个字符变化到 B 的j - 1 个字符的最小操作数,A前 i 个字符已经和Bj - 1匹配,那么增加一个字符bj后才能做到ai bj 匹配。再考虑删除,先上状态:f[i - 1][j] + 1 删除之前,必须考虑a[i - 1] 已经和 b[j] 匹配上,才能实现删除一个字符匹配成功。而修改操作:考虑a[i - 1] 和 b[j - 1] 已经匹配,然后判断a[i] == b[j] 考虑是否 + 1。

Code:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

const int N = 1e3 + 10;

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 ++)
        {
            f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;
            f[i][j] = min(f[i][j], f[i - 1][j - 1] + (a[i] != b[j]));
        }
    
    cout << f[n][m] << endl;
    
    return 0;
}
posted @ 2020-09-13 21:24  Hayasaka  阅读(60)  评论(0编辑  收藏  举报