P2758 编辑距离(dp)
https://www.luogu.com.cn/problem/P2758
https://leetcode.cn/problems/edit-distance/description/
设 和 是两个字符串。我们要用最少的字符操作次数,将字符串 转换为字符串 。这里所说的字符操作共有三种:
- 删除一个字符;
- 插入一个字符;
- 将一个字符改为另一个字符。
均只包含小写字母。
输入格式
第一行为字符串;第二行为字符串;字符串 的长度均小于。
输出格式
只有一个正整数,为最少字符操作次数。
输入
sfdqxbw
gfdgw
输出
4
说明/提示
对于 的数据,。
转移方程: 如果a[i]与b[j]相等:
那么dp[i][j] = dp[i - 1][j - 1],因为在a前i - 1个字符串最少能通过dp[i - 1][j - 1]次操作转化为b前j - 1个字符串的基础上什么都不干,a前i个字符串也能通过最少dp[i - 1][j - 1]次操作就能与b前j个字符相等,dp[i][j] 自然就与 dp[i - 1][j - 1] 相等了。
如果a[i]与b[j]不相等:有以下三种情况
-
添加:
在这个情况下,我们知道既然要从dp[i][j - 1]转移到dp[i][j],说明dp[i][j - 1]在之前的dp中已经算好了,dp[i][j - 1]表示a前i个字符串最少能通过dp[i][j - 1]次操作转化为b前j - 1个字符串。
那怎么才能让a前i个字符串最少能通过dp[i][j]次操作转化为b前j个字符串呢?
只要在a[i]后面加一个b[j],此时如果在a前i个字符上做dp[i][j - 1]同样的操作,我们可以保证a前i个字符与b前j - 1个字符相等,但由于在a后面加了一个字符与b[j]相等。
所以在a前i个字符上做dp[i - 1][j - 1]同样的操作后就与b前j个字符相等了。因为要做一次添加操作。
所以dp[i][j] = dp[i][j - 1] + 1。 -
删除:dp[i - 1][j] + 1 \rightarrow→ dp[i][j]
在这个情况下,我们知道既然要从dp[i - 1][j]转移到dp[i][j],说明dp[i - 1][j]在之前的dp中已经算好了,dp[i - 1][j]表示a前i - 1个字符串最少能通过dp[i - 1][j]次操作转化为b前j个字符串。
那怎么才能让a前i个字符串最少能通过dp[i][j]次操作转化为b前j个字符串呢?
只要把a[i]删掉,此时如果在a前i - 1个字符上做dp[i - 1][j]同样的操作,我们可以保证a前i -1个字符与b前j个字符相等。
因为我们把a[i]删掉了,所以做与dp[i - 1][j]同样的操作,我们可以保证a前i个字符与b前j个字符相等。
所以dp[i][j] = dp[i - 1][j] + 1。 -
替换:dp[i - 1][j - 1] + 1 \rightarrow→ dp[i][j]
只需要把a[i]替换成b[j]就行了,所以dp[i][j] = dp[i - 1][j - 1] + 1。
洛谷
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=5e3+100;
int dp[maxn][maxn];
char s[maxn],t[maxn];
int main(){
memset(dp,0x3f3f3f3f,sizeof(dp));
scanf("%s%s",s+1,t+1);
int lena=strlen(s+1);
int lenb=strlen(t+1);
for (int i = 1; i <= lena; i++) dp[i][0] = i;
for (int i = 1; i <= lenb; i++) dp[0][i] = i;
dp[0][0]=0;
for(int i=1;i<=lena;i++){
for(int j=1;j<=lenb;j++){
if(s[i]==t[j]){
dp[i][j]=min(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;
}
}
}
cout<<dp[lena][lenb]<<endl;
}
leetcode
class Solution {
public:
//我们用 D[i][j] 表示 A 的前 i 个字母和 B 的前 j 个字母之间的编辑距离
int minDistance(string word1, string word2) {
int n=word1.size(),m=word2.size();
int dp[n+1][m+1];
memset(dp,0x3f3f3f3f,sizeof(dp));
for(int i=0;i<n+1;i++){
dp[i][0]=i;
}
for(int j=0;j<m+1;j++){
dp[0][j]=j;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(word1[i-1]==word2[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;
}
}
}
return dp[n][m];
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2023-06-24 TensorFlow10.5 卷积神经网络-ResNet与DenseNet及ResNet实战
2023-06-24 TensorFlow10.4 卷积神经网络-batchnorm
2023-06-24 TensorFlow10.3 卷积神经网络-经典卷积网络(VGG,GoogLeNet)
2023-06-24 TensorFlow10.2 卷积神经网络-CIFAR100 实战