最短编辑距离(字符串的修改)

最短编辑距离(字符串的修改)

题目来源:acwing题库江西理工大学OJ
题目地址:acwing江理OJ

题目描述:
给定两个字符串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

很典型的一道动态规划问题,很适合培养入门级别的小白入手分析。
思路分析:

//分类,对于最后一个数进行操作,分为三类,分别是删除操作、增加操作和替换操作
//删除操作如何表示?假设我们现在应该要执行的操作是删除操作,那么应该是f[i][j]=f[i-1][j]+1,为什么呢?
//因为如果要删除a中第i个字母的话,那么根据前面我们对于f[i][j]的定义不难推断出,a中的前i-1个字母应该和b中前j个字母是匹配的。(不然不会执行删除操作)
//所以我们进行删除操作的时候只需要在前一步的情况下加上1即可。
//增加操作如何表示?假设我们现在应该要执行增加操作,那么应该是f[i][j]=f[i][j-1]+1,.为什么呢?
//根据定义,我们是希望通过对于最后一步的操作来实现a中前i个字母和b中前j个字母相等。
//所以我们根据此定义可以推出,我们在没有执行增加操作之前,我们的a中的前i个字母是和b中前j-1个字母相等的。
//因为只有这样,我们做增加操作才能够达到我们的目的。
//最后一个,替换操作如何表示?假设我们现在应该要执行的操作是替换操作,那么我们应该考虑一个问题。
//什么问题呢?如果我们的最后一个字母a[i]等于a[j]的话,那我们就不需要进行操作了,所以此时f[i][j]=f[i-1][j-1]。
//如果a[i]不等于b[j],那么我们就要执行替换操作,那么和上面分析的思路一样。
//我们可以通过替换来达到我们所需要的“a中前i个字母和b中前j个字母一样“,那么根据这个定义,
//我们就可以推理出,我们a中前i-1个字母和b中前j-1个字母肯定是一样的,因为只有这样我们才能通过替换操作来达到我们的目的
//那么所有情况我们都分析出来了,接下来我们就可以尝试着写一些代码

AC代码+注释如下:



#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
char a[N], b[N];
int f[N][N] = {};//f[i][j]表示将a中前i个字母变得和b中前j个字母相同所需要的最小操作次数(思考步骤是关键步骤)
int n, m;
int main()
{
	scanf("%d%s%d%s", &n,a+1,&m,b+1);
	//接下来考虑一下初始化的问题,如果我们用a中0个字符去对应b中j个字符,那么我们就要进行j次增加操作,那么我们就要把
	//f[0][j]=j,然后如果我们用a中i个字母去对应b中0个字符的话,我们就需要进行i次删除操作,也就是f[i][0]=i;
	//这个的话大家可以根据前面我们对于f[i][j]的定义去理解一下,为什么是这样子初始化
	for (int i = 0; i <= n; i++)//表示初始化用a中i个字母去对应b中j个字母
		f[i][0] = i;
	for (int j = 0; j <= m; j++)//表示初始化用a中0个字母去对应b中j个字母
		f[0][j] = j;
	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] + 1);
				else
					f[i][j] = min(f[i][j], f[i - 1][j - 1]);
		}
	printf("%d", f[n][m]);
	return 0;
}

视频讲解如下:

最短编辑距离(字符串的修改)

好啦!这篇博客就这么愉快地结束啦!
我也要朝着我的目标继续前进了!
每篇博客后面都附上一句话。

关关难过关关过,长路漫漫路灿灿。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值