动态规划——编辑距离

编辑距离不仅是动态规划里很经典的例题,也是面试中高频出现的题目,需要我们好好掌握。

学完本文,你可以尝试实现

洛谷P2758 编辑距离

Leetcode 72.编辑距离

题目介绍

洛谷例题

题目描述

设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:

1、删除一个字符;

2、插入一个字符;

3、将一个字符改为另一个字符;

!皆为小写字母!

输入格式

第一行为字符串A;第二行为字符串B;字符串A和B的长度均小于2000。

输出格式

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

扫描二维码关注公众号,回复: 13533676 查看本文章

输入输出样例

输入 1

sfdqxbw
gfdgw

输出 1

4

Leetcode例题

 

编辑距离详解过程

前言

图片.png

如果你刚刚听说动态规划,还不太明白 dp 为啥要定义成这样,转移方程是啥。
欢迎来看一下这篇题解,看完能稍微理解一下动态规划到底做了什么事?
或许芭。

思路

1.动态规划

2.定义 dp[i][j]

  21. dp[i][j] 代表 word1 中前 i 个字符,变换到 word2 中前 j 个字符,最短需要操作的次数
  22. 需要考虑 word1 或 word2 一个字母都没有,即全增加/删除的情况,所以预留 dp[0][j] 和 dp[i][0]

3.状态转移

  31. 增,dp[i][j] = dp[i][j - 1] + 1
  32. 删,dp[i][j] = dp[i - 1][j] + 1
  33. 改,dp[i][j] = dp[i - 1][j - 1] + 1
  34. 按顺序计算,当计算 dp[i][j] 时,dp[i - 1][j] , dp[i][j - 1] , dp[i - 1][j - 1] 均已经确定了
  35. 配合增删改这三种操作,需要对应的 dp 把操作次数加一,取三种的最小
  36. 如果刚好这两个字母相同 word1[i - 1] = word2[j - 1] ,那么可以直接参考 dp[i - 1][j - 1] ,操作不用加一

图解

绿色:增
红色:删
黄色:改

 大功告成!

解题代码 洛谷

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
//楼上为一些头文件
using namespace std ;

const int kMaxLen = 2000 + 5 ;//字符串长度最大为2000,定义数组的时候就加个5

int len1 , len2 , dp[kMaxLen][kMaxLen] ;
//len1表示字符串A的长度
//len2表示字符串B的长度
string s1 , s2 ;
//s1:A字符串
//s2:B字符串
int main(){
	
    cin >> s1 >>  s2 ;//输入字符串
	
    len1 = s1.size() ;
    len2 = s2.size() ;
    //用size()函数取长度
	
    for(int i = 1 ; i <= len1 ; i++ ){
    	dp[i][0] = i ;
    }
    for(int i = 1 ; i <= len2 ; i++ ){
        dp[0][i] = i ;
    }
	
    //dp部分代码:
    
    for(int i = 1 ; i <= len1 ; i++ ){//枚举A字符串的字符
        for(int j = 1 ; j <= len2 ; j++ ){//枚举B字符串的字符
            if(s1[i - 1] == s2[j - 1])//字符串是从零开始的所以要减一
                dp[i][j] = dp[i - 1][j - 1] ;//不变
            }
            else{
                dp[i][j] = min(min(dp[i][j - 1] + 1 , dp[i - 1][j] + 1) , dp[i - 1][j - 1] + 1) ;
                //删除,添加,替换
            }
        }
    }
	
    cout << dp[len1][len2] ; //输出结果
	
	return 0 ;结束了

}

解题代码 Leetcode

class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1 = word1.length();
	    int len2 = word2.length();
        vector<vector<int> > dp(len1+1,vector<int>(len2+1,0));
        for(int i = 0;i<=len1;i++) dp[i][0] = i;
        for(int j = 0;j<=len2;j++) dp[0][j] = j;
        for(int i = 1;i<=len1;i++){
            for(int j = 1;j<=len2;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],dp[i][j-1],dp[i-1][j-1]})+1;
                }
            }
        }
        return dp[len1][len2];
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_44572229/article/details/121790305