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

动态规划算法之编辑距离

一、什么是编辑距离

编辑距离(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;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>