首页 > 其他分享 >最短编辑距离

最短编辑距离

时间:2024-09-09 21:36:24浏览次数:1  
标签:min int 字母 d% 距离 最短 编辑 操作 scanf


算法1

(线性DP) $O(n^2)$

1.状态定义

f[i][j] : 所有将a[1 ~ i] 变成 b[1 ~ j]的操作方式的操作次数的最小值

2.状态计算:

如何分类分类方式一般考虑的是最后一步

a的前i个字母,b的前j个字母,共有三种操作;

1.删除:a[1 到 i - 1] == b[1 到 j] ,删除 a[i] ,即方程为 f[i-1][j] + 1;

2.增加:a[1 到 i] == b[1 到 j - 1], 增加使a[i] = b[j]; ,即方程为 f[i][j-1] + 1;

3.更改操作:

这里我们可以再划分为不用修改的情况和修改的情况

 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);

,其中 +1 表示最后一步的操作;

3.边界情况

我们需要考虑两种情况

1.只能做增加操作:a的前0个字母与b的前1~j的字母进行匹配时

2.只能做删除操作:a的前1~j个字母与b的前0个字母进行匹配时

	for(int i = 1; i <= m; i++) f[0][i] = i;  //增加操作
	for(int i = 1; i <= n; i++) f[i][0] = i;  //删除操作

C++ 代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1010;

int n,m;
char a[N],b[N];
int f[N][N];  //f[i][j] 表示n的前i个字母变成b的前j个字母的操作次数的最小值

int main() {
	scanf("%d%s",&n,a + 1);
	scanf("%d%s",&m,b + 1);

	//处理边界情况
	for(int i = 1; i <= m; i++) f[0][i] = i;  //增加操作
	for(int i = 1; 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",f[n][m]);
	return 0;

}

标签:min,int,字母,d%,距离,最短,编辑,操作,scanf
From: https://www.cnblogs.com/ltphy-/p/18405395

相关文章