动态规划—最小编辑距离

题目来源:牛客网链接:https://www.nowcoder.com/questionTerminal/9649617be3bf42288f50758df4310655

UNIX系统下有一个行编辑器ed,它每次只对一行文本做删除一个字符、插入一个字符或替换一个字符三种操作。例如某一行的内容是“ABC”,经过把第二个字符替换成“D”、删除第一个字符、末尾插入一个字符“B”,这三步操作后,内容就变成了“DCB”。即“ABC”变成“DCB”需要经过3步操作,我们称它们的编辑距离为3。
现在给你两个任意字符串(不包含空格),请帮忙计算它们的最短编辑距离。

输入描述:
输入包含多组数据。

每组数据包含两个字符串m和n,它们仅包含字母,并且长度不超过1024。

输出描述:
对应每组输入,输出最短编辑距离。
示例1
输入
ABC CBCD
ABC DCB
输出
2
3

分析:

假设序列S和T的长度分别为m和n, 两者的编辑距离表示为dp[m][n]. 则对序列进行操作时存在以下几种情况:

  • a, 当S和T的末尾字符相等时, 对末尾字符不需要进行上述定义操作中(亦即"编辑")的任何一个, 也就是不需要增加计数. 则满足条件: dp[m][n] = dp[m - 1][n - 1].
  • b, 当S和T的末尾字符不相等时, 则需要对两者之一的末尾进行编辑, 相应的计数会增加1.
  • b1, 对S或T的末尾进行修改, 以使之与T或S相等, 则此时dp[m][n] = dp[m - 1][n - 1] + 1;
  • b2, 删除S末尾的元素, 使S与T相等, 则此时dp[m][n] = dp[m - 1][n] + 1;
  • b3, 删除T末尾的元素, 使T与S相等, 则此时dp[m][n] = dp[m][n - 1] + 1;
  • b4, 在S的末尾添加T的尾元素, 使S和T相等, 则此时S的长度变为m+1, 但是此时S和T的末尾元素已经相等, 只需要比较S的前m个元素与T的前n-1个元素, 所以满足dp[m][n] = dp[m][n - 1] + 1;
  • b5, 在T的末尾添加S的尾元素, 使T和S相等, 此时的情况跟b4相同, 满足dp[m][n] = dp[m - 1][n] + 1;
  • c, 比较特殊的情况是, 当S为空时, dp[0][n] = n; 而当T为空时, dp[m][0] = m; 这个很好理解, 例如对于序列""和"abc", 则两者的最少操作为3, 即序列""进行3次插入操作, 或者序列"abc"进行3次删除操作.

所以, 以上我们不难推出编辑距离的动态规划方程为:

以字符串str1="ALGORITHM",str2="ALTRUISTIC"为例,m=strlen(str1)=9,n=strlen(str2)=10,最小编辑距离推导过程如下,先计算dp[1][1],dp[1][2]...dp[1][10],再计算dp[2][1]...dp[2][10]...。最终最小编辑距离=dp[m][n]=6.

代码如下:

#include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>//min()包含头文件
using namespace std;
int main(){
	char str1[1025],str2[1025];长度不超过1024,长度最小要声明为1024+1,因为字符串末尾有空字符。
	int n,m,temp;
	while(cin>>str1>>str2){//循环输入两个字符串
		m=strlen(str1);
		n=strlen(str2);
		vector<vector<int>> dp(m+1,vector<int>(n+1,0));//生成一个m+1行n+1列的二维矩阵记录当前的状态值
		//初始化
		for(int i=1;i<=m;i++)//dp[i][0]=i,例如dp[2][0]表示一个长度为2的字符串str1与一个空字符串str2的最小编辑距离为2(即依次将str1中的字符添加到str2中)
			dp[i][0]=i;
		for(int j=0;j<=n;j++)//dp[0][j]=j,例如dp[0][1]表示一个空字符串str1与一个长度为1的字符串str2的最小编辑距离为1(即依次将str2中的字符添加到str1中)
			dp[0][j]=j;
		dp[0][0]=0;//空字符串与空字符串之间的最小编辑距离为0
		for(int i=1;i<=m;i++){
			for(int j=1;j<=n;j++){
				if(str2[j-1]==str1[i-1])//注意:字符串str1和str2中的索引是从0开始的,而1<=i<=m,1<=j<=n,所以这里的i和j要减1
					dp[i][j]=dp[i-1][j-1];
				else{
					temp=min(dp[i][j-1],dp[i-1][j]);
					dp[i][j]=min(temp,dp[i-1][j-1])+1;
				}	
			}
		}
		cout<<dp[m][n]<<endl;//最终的dp[m][n]为两字符串之间的最小编辑距离
	}
	return 0;
}

 

  • 11
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值