【动态规划】(一)编辑距离

动态规划算法之编辑距离

一、什么是编辑距离

编辑距离(Edit distance,简称EDS),就是求字符串s1到字符串s2的最少修改次数。每次修改的方式如下:
1.增加一个字符。如: a b c abc abc -> a b c d abcd abcd
2.删除一个字符。如: a b c abc abc -> a b ab ab
3.修改一个字符。如: a b c abc abc -> a b d abd abd

二、编辑距离怎么求

1.深搜枚举

深搜枚举的时间复杂度很高。假设字符串只有小写字母,最长的字符串长度为 n n n,则时间复杂度为 O ( 2 6 n ) O(26^n) O(26n),远远超出题目范围。

2.动态规划(重点)

举个例子

h a s has has h a v e have have为例,要求 h a s has has h a v e have have的编辑距离,就可以把它转化成 h a s has has h a v hav hav的编辑距离。那么我们就可以创建一个 d p dp dp数组,其中, d p [ i ] [ j ] dp[i][j] dp[i][j]表示从a串的第一个字符到第i个字符与b串第一个字符到第j个字符的编辑距离。如下图所示:

^have
^0
h
a
s

第一步, d p [ 0 ] [ 0 ] dp[0][0] dp[0][0]将更新为0。毕竟 空串 空串 空串 空串 空串 空串与的编辑距离也是0嘛。

^have
^01234
h1
a2
s3

第二步,更新 d p [ 0 ] [ j ] dp[0][j] dp[0][j] d p [ i ] [ 0 ] dp[i][0] dp[i][0],其中, d p [ i ] [ 0 ] = i dp[i][0] = i dp[i][0]=i, d p [ 0 ] [ j ] = j dp[0][j] = j dp[0][j]=j

^have
^01234
h10
a2
s3

第三步,就要正式模拟了。先看 h h h h h h,由于他们相等,那就是 d p [ i − 1 ] [ j − 1 ] dp[i - 1][j - 1] dp[i1][j1]了,因为这两个字符相等,不用做任何改变。

^have
^01234
h101
a2
s3

第四步,再看 h h h a a a,他们不相同,就要从 d p [ i − 1 ] [ j ] dp[i - 1][j] dp[i1][j] d p [ i − 1 ] [ j − 1 ] dp[i - 1][j - 1] dp[i1][j1] d p [ i ] [ j − 1 ] dp[i][j - 1] dp[i][j1]里面选一个最小值,加上1。加上一的原因是要对某个字符进行改变。

^have
^01234
h10123
a21012
s32122

第五步,以此类推。最后, d p [ a l e n ] [ b l e n ] dp[alen][blen] dp[alen][blen]就是答案。

关键来了!

得出的转移方程:
1. d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] , a [ i ] = b [ j ] dp[i][j]=dp[i - 1][j - 1],a[i] = b[j] dp[i][j]=dp[i1][j1],a[i]=b[j]
2. d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j − 1 ] , d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + 1 , a [ i ] ! = b [ j ] dp[i][j]=min(dp[i - 1][j - 1],dp[i - 1][j],dp[i][j - 1])+1,a[i]!=b[j] dp[i][j]=min(dp[i1][j1],dp[i1][j],dp[i][j1])+1,a[i]!=b[j]
边界值为:
d p [ i ] [ 0 ] = i , d p [ 0 ] [ j ] = j dp[i][0]=i,dp[0][j]=j dp[i][0]=i,dp[0][j]=j
上代码!

#include<iostream>
#include<cstring>
using namespace std;
int dp[105][105];
int min(int a, int b, int c){
	if(a < b){
		if(a < c)return a;
		return c;
	}
	if(b < c)return b;
	return c;
}
int main(){
	string s1, s2;
	cin >> s1 >> s2;
	int lena, lenb;
	lena = s1.length();//可用s1.size()代替,注意导入cstring库
	lenb = s2.length();
	if(s1[0] == s2[0]){
		dp[0][0] = 0;
	} else {
		dp[0][0] = 1;
	}
	for(int i = 0; i < lenb; i++){
		dp[0][i] = i;
	}
	for(int i = 0; i < lena; i++){
		dp[i][0] = i;
	}
	for(int i = 1; i < lena; i++){
		for(int j = 1; j < lena; j++){
			if(s1[i] == s2[j]){
				dp[i][j] = dp[i - 1][j - 1];
			} else {
				dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - 1], dp[i][j - 1]) + 1;
			}
		}
	}
	cout << dp[lena][lenb];
	return 0;
}
  • 19
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
动态规划可以用来求解编辑距离问题。编辑距离是指将一个字符串转换为另一个字符串所需的最小字符操作次数。字符操作包括删除一个字符、插入一个字符和将一个字符替换为另一个字符。 为了求解编辑距离,我们可以使用一个二维数组dp,其中dp[i][j]表示将字符串A的前i个字符转换为字符串B的前j个字符的最优编辑距离。 我们可以使用以下状态转移方程来计算dp数组的值: 1. 当i=0时,dp[j]表示将空字符串转换为字符串B的前j个字符的最优编辑距离,即插入操作的次数,所以dp[j]=j。 2. 当j=0时,dp[i]表示将字符串A的前i个字符转换为空字符串的最优编辑距离,即删除操作的次数,所以dp[i]=i。 3. 当A[i-1]=B[j-1]时,这两个字符相等,不需要进行任何操作,所以dp[i][j]=dp[i-1][j-1]。 4. 当A[i-1]!=B[j-1]时,可以进行三种操作:替换操作、插入操作和删除操作。dp[i][j]可以取这三种操作的最小值,即dp[i][j]=min(dp[i-1][j-1], dp[i][j-1], dp[i-1][j])+1。 最后,dp[m][n]即为将字符串A转换为字符串B的最优编辑距离,其中m和n分别表示字符串A和字符串B的长度。 以下是使用动态规划解决编辑距离问题的示例代码: ```cpp string a = "sfdqxbw"; string b = "gfdgw"; int dp[MAXN][MAXN]; void solve() { int i, j; for (i = 1; i <= a.length(); i++) dp[i][0 = i; for (j = 1; j <= b.length(); j++) dp = j; for (i = 1; i <= a.length(); i++) { for (j = 1; j <= b.length(); j++) { if (a[i - 1 == b[j - 1]) dp[i][j = dp[i - 1][j - 1]; else dp[i][j = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1; } } } ``` 以上是使用动态规划求解编辑距离问题的方法。通过计算dp数组,我们可以得到将字符串A转换为字符串B的最小字符操作次数。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* *2* [动态规划法求解编辑距离问题](https://blog.csdn.net/weixin_42729072/article/details/105160948)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值