题目链接:

动态规划的思路:
1、状态定义:题目要求A==>B的最少操作次数,我们用二维数组 dp[i][j] 来表示 A 的前 i 个字母转换为 B 的前 J 个字母需要的最少操作次数。
2、状态转移:这里有两种情况,当 A[i] == B[j] 的时候,我们直接用前面的状态 dp[i-1][j-1]。当 A[i] != B[j] 的时候,①将 A[i] 改写成 B[j] , dp[i][j] = dp[i-1][j-1]+1; ②将B末尾 B[j] 插入到 A 末尾A[i],dp[i][j] = dp[i][j+1]+1;③ 将 A末尾 A[i] 删除,dp[i][j] = dp[i-1][j]+1。
3、初始化:①当 B为空字符串时, dp[i][0] = i,表示将 A 的前 i 个字符全部删除,需要 i 次操作。②当 A 为空字符串时, dp[0][i] = i, 表示需要插入 j 次字符,才能使得字符串 A 等于字符串 B。
4、答案: dp[A的字符串长度][B的字符串长度];
线性DP代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2020;
string s1, s2;
int dp[N][N];
int main(){
cin >> s1 >> s2;
//避免状态转移的时候出现负数下标
s1 = " " + s1;
s2 = " " + s2;
//长度
int n1 = s1.size(), n2 = s2.size();
//题目要我们求最少的操作次数 将dp数组答案初始化N
for(int i = 1;i < n1; i++){
for(int j =1;j <= n2; j++){
dp[i][j] = N;
}
}
//dp数组初始化状态
for(int i = 1; i < n1; i++){
dp[i][0] = i;
}
for(int i = 1; i < n2; i++){
dp[0][i] = i;
}
//状态转移
for(int i = 1;i < n1; i++){
for(int j = 1; j < n2; j++){
if(s1[i] == s2[j]){
dp[i][j] = dp[i-1][j-1];
}
else{
dp[i][j]=min({dp[i-1][j-1]+1, dp[i-1][j]+1, dp[i][j-1]+1});
}
}
}
cout << dp[n1-1][n2-1] << endl;
return 0;
}