最小编辑代价 动态规划

这篇博客探讨了如何利用动态规划算法解决最小编辑代价问题。内容包括题目描述、输入输出示例以及详细的解题思路。作者指出,关键在于定义状态dp[i][j]表示将str1的前i位编辑成str2的前j位的最小代价,并列举了三种状态转移情况:替换、删除和插入。最后给出了实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目描述:来源于《算法与数据结构题目最优解》左程云著

给定两个字符串str1和str2,再给定三个整数ic、dc和rc,分别代表插入、删除和替换一个字符的代价,返回将str1编辑成str2的最小代价


2、输入

abc

adc

5 3 2

abc

adc

5 3 100

abc

abc

5 3 2

ab12cd3

abcdf

5 3 2


3、输出

2

8

0

8


4、题目解析

1)题目的关键还是在于找状态,这个题目的状态dp[i][j]就代表用str1的前 i 位 编辑成 str2 的前 j 位的最小代价。

2)关键点之二在于初始状态的时候,字符串的初始状态一般是空字符串,这样考虑起来就比较容易了,我一开始是从第一个字符开始的,其实也可以,不过不如空串直观。

3)关键点之三在于状态的迭代,这个的情况比较多,想从str1的前 i 个得到 str2的前 j 个,

a、可以是前 i-1 个组成了 前 j-1 个,这样就用str1第 i 个 替换成str2的第 j 个就行了,不过如果str1[i]==str2[j], 就不用替换了(我就没考虑到这种情况);

b、可以是前 i-1个组成了前 j 个,那么只需要删除第 i 个

c、可以是前 i 个组成了前 j-1 个,那么只需要再插入一个。


5、代码如下:

#include<iostream>
#include<vector>
#include<string>

using namespace std;
int getMin(int, int);
int main() {
	string str1, str2;
	int ic, dc, rc;//插入、删除、替换
	int len1, len2;
	int i, j;
	getline(cin, str1);
	getline(cin, str2);
	cin >> ic >> dc >> rc;
	len1 = str1.length();
	len2 = str2.length();
	vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1));//dp[i][j]代表用去str1的前i为变成str2的前j位的最小代价,并且初始化从空字符串开始
	//下面对dp进行赋值,从dp[0][0]代表空字符串
	dp[0][0] = 0;
	for (i = 1; i < len1 + 1; ++i) {
		dp[i][0] = dp[i - 1][0] + dc;
	}
	for (j = 1; j < len2 + 1; ++j) {
		dp[0][j] = dp[0][j - 1] + ic;
	}
	for (i = 1; i < len1 + 1; ++i) {
		for (j = 1; j < len2 + 1; ++j) {
			if (str1[i] == str2[j])//一定要注意考虑str1[i]是否和str2[j]相等
				dp[i][j] = dp[i - 1][j - 1];
			else
				dp[i][j] = dp[i - 1][j - 1] + rc;
			dp[i][j] = getMin(dp[i][j],dp[i][j-1]+ic);
			dp[i][j] = getMin(dp[i][j], dp[i - 1][j] + dc);
		}
	}
	cout << "the minimum value is: " << dp[len1][len2] << endl;
}
int getMin(int v1, int v2) {
	if (v2 < v1)return v2;
	return v1;
}

### 动态规划实现最小编辑距离 最小编辑距离问题是经典的动态规划问题之一,其目标是找到将一个字符串转换为另一个字符串所需的最少操作次数。这些操作通常包括插入、删除和替换字符。 以下是基于动态规划方法的C语言实现代码: ```c #include <stdio.h> #include <string.h> // 取三个整数中的最小值 int min(int a, int b, int c) { int temp = (a < b) ? a : b; return (temp < c) ? temp : c; } // 计算两个字符串之间的最小编辑距离 int editDistance(char* str1, char* str2) { int len1 = strlen(str1); int len2 = strlen(str2); // 创建二维数组存储中间结果 int dp[len1 + 1][len2 + 1]; // 初始化边界条件 for (int i = 0; i <= len1; i++) { dp[i][0] = i; // 当第二个字符串为空时,需要执行i次删除操作 } for (int j = 0; j <= len2; j++) { dp[0][j] = j; // 当第一个字符串为空时,需要执行j次插入操作 } // 填充dp表 for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (str1[i - 1] == str2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; // 字符相等时不需额外操作 } else { int insertion = dp[i][j - 1] + 1; // 插入操作 int deletion = dp[i - 1][j] + 1; // 删除操作 int replacement = dp[i - 1][j - 1] + 1; // 替换操作 dp[i][j] = min(insertion, deletion, replacement); // 选取最优解 } } } return dp[len1][len2]; } int main() { char str1[100], str2[100]; printf("Enter first string: "); scanf("%s", str1); printf("Enter second string: "); scanf("%s", str2); int result = editDistance(str1, str2); printf("Minimum Edit Distance between '%s' and '%s': %d\n", str1, str2, result); return 0; } ``` #### 解析 该程序的核心在于构建了一个`dp`表格用于记录子问题的结果[^2]。 - `dp[i][j]`表示将`str1`的前`i`个字符转换成`str2`的前`j`个字符所需要的最小编辑距离。 - 边界条件初始化:当其中一个字符串为空时,另一字符串的所有字符都需要被插入或删除。 - 对于每个位置`(i,j)`,如果对应的字符相同,则无需任何操作;否则考虑三种可能的操作(插入、删除、替换),并选择其中代价最小的一种作为最终结果[^3]。 此算法的时间复杂度为O(mn),空间复杂度同样为O(mn),其中m和n分别为两字符串的长度[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值