P2758 编辑距离(dp)

https://www.luogu.com.cn/problem/P2758

https://leetcode.cn/problems/edit-distance/description/
AB 是两个字符串。我们要用最少的字符操作次数,将字符串 A 转换为字符串 B。这里所说的字符操作共有三种:

  • 删除一个字符;
  • 插入一个字符;
  • 将一个字符改为另一个字符。
    A,B均只包含小写字母。

输入格式
第一行为字符串A;第二行为字符串B;字符串 A,B 的长度均小于2000

输出格式
只有一个正整数,为最少字符操作次数。

输入
sfdqxbw
gfdgw
输出
4
说明/提示
对于 %100 的数据,1|A|,|B|2000

转移方程: 如果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][j1]+1→→dp[i][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];
    }
};
posted @   lipu123  阅读(10)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 阿里最新开源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 实战
点击右上角即可分享
微信分享提示