leetcode 72编辑距离

本文深入探讨了使用动态规划解决字符串编辑距离问题的方法,详细解释了递推式的由来和状态转移方程,通过具体例子说明了匹配过程中插入、删除和替换操作的计算逻辑,并提供了优化内存消耗的实现方案。

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

想到动态规划是第一步,其次hhh。

递推式怎么来的???

先看官方解释:

dp[i][j]表示str1前i个字符与str2前j个字符匹配所需的最少次数;str1="horse",str2="ros"

当我们知道dp[i][j],dp[i+1][j],dp[i][j+1]后就可以分两种情况来讨论了;

1---当str1[i+1]=str2[j+1]时,就等于给的例子中,匹配hors和ros时;

dp[i+1][j+1]=1+{dp[i][j]-1,dp[i][j+1],dp[i+1][j]};

我们一个一个看;最重要的是前面的1代表的是什么操作;

dp[i][j]表示hor,ro匹配的最少次数,你管我怎么匹配得到的,反正我现在已经得到ro了,那么最后的s就不用特殊处理了;所以-1+1=0;

dp[i][j+1]表示hor,ros匹配的最少次数,我都匹配完了,直接把刚加入的s给删掉不就行了,所以1对应的是删除操作;

dp[i+1][j]表示hors,ro匹配的最少次数,同样的,我在最后再添加一个s不就得了,所以这里1对应的是插入操作;

------------更新

实际上;对于上面这种情况,是不需要取最小值的;

我们比较 dp[i][j]-1(表示hor,ro匹配的最少次数),dp[i][j+1]的大小(表示hor,ros匹配的最少次数);

等价于比较dp[i][j]和dp[i][j+1]+1的大小;dp[i][j+1]+1中的1可以看做hor匹配ro,最后加上一个s;有没有发现是等于dp[i][j]的;但这不一定是最优解

所以dp[i][j+1]+1>=dp[i][j];

同理我们比较dp[i][j]和dp[i-+1][j]+1的大小;我的1可以看做删除hors后面的s,这消耗一个操作,就等价于dp[i][j]了;

所以dp[i+1][j]+1>=dp[i][j];

所以压根不需要比较,此时可以直接得出dp[i+1][j+1]==dp[i][j];

-------------

2---当str1[i+1]=str2[j+1]时,就等于给的例子中,匹配horse和ros时;

dp[i+1][j+1]=1+{dp[i][j],dp[i][j+1],dp[i+1][j]};

同样的----

dp[i][j]表示hors,ro匹配的最少次数,你管我怎么匹配得到的,反正我现在已经得到ro了,那么最后的e直接替换成s不就得了;

所以这里的1代表的是替换操作;

dp[i][j+1]表示hors,ros匹配的最少次数,我都匹配完了,直接把刚加入的e给删掉不就行了,所以1对应的是删除操作;

dp[i+1][j]表示horse,ro匹配的最少次数,同样的,我在最后再添加一个s不就得了,所以这里1对应的是插入操作;

后两种情况其实和上面第一种情况分析一样,唯一不同的是对dp[i][j]的分析;

初始值???

dp[0][0]=0;

dp[0][i]=i;//表示i个插入操作

dp[i][0]=i;//表示i个删除操作

修改后(我还是很无语,好像同一个答案每次提交结果不是一样的,相差几ms,但这却足以让单题排名差距很大hhh)

----------------------------------------------------------------------------------------------------------------------------------------------

内存消耗这块我用两个等长数组代替了二维数组hhh,很多题目都可以这样做。。。

class Solution {
public:
int minDistance(string word1, string word2) {
	int N = word1.length();
	int M = word2.length();
    if (M == 0)
		return N;
	//vector<vector<int>>v(N+1, vector<int>(M+1, 0));
	vector<int>v(1+N, 0);
	vector<int>v2(N+1, 0);

	//边界初始化
	for (int i = 0; i <= N; i++) {
		v[i] = i;
	}
	for (int i = 1; i <= M; i++) {
		v2[0] = i;
		for (int j = 1; j <= N; j++) {
			int tem = (word2[i-1] == word1[j-1]) ? 1 : 0;			
			v2[j] = 1 + min(min(v[j - 1] - tem, v[j]), v2[j-1]);
			//cout << word1.substr(0, i) << " " << word2.substr(0, j) << " " << v2[j] << endl;
		}
		v = v2;
	}
	return v2[N];
}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值