题目描述
设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。这里所说的字符操作共有三种:
1、删除一个字符;
2、插入一个字符;
3、将一个字符改为另一个字符;
!皆为小写字母!
输入格式
第一行为字符串A;第二行为字符串B;字符串A和B的长度均小于2000。
输出格式
只有一个正整数,为最少字符操作次数。
输入输出样例
输入 #1
sfdqxbw gfdgw
输出 #1
4令dp[i][j]代表的含义为将a串的前i个字符转化为b串的前j个字符所需要的最少操作次数。在写转移方程的时候考虑这么几种情况:1.a[i-1]==b[j-1](a[i-1]为a的第i个字符:则dp[i][j]=dp[i-1][j-1]相等时无需进行操作。2.a[i-1]!=b[j-1]:dp[i][j]=min(dp[i-1][j-1]+1,dp[i][j-1]+1,dp[i-1][j]+1) 含义分别为替换,插入和删除。替换比较好理解,直接在dp[i-1][j-1]基础上加上替换的一步操作即可。插入因为是在a[i]插入了一个与b[j]相同的字符,所以这里认为a串第i个之前与b串第j-1个之前的字符经过dp[i][j-1]次操作匹配了,只需要再增加一次添加操作。对a的插入可以看作与对b的删除互为逆运算,类比一下可理解。可以联想一下stud转换为study,求dp[4][5]。按照人的思维肯定考虑插入,相当于dp[4][4]+1。
#include <bits/stdc++.h>
using namespace std;
char a[3010];
char b[3010];
int dp[3010][3010]={0};//dp[i][j]表示a串的前i个字符转换成b串的前j个字符需要的最少步数
int mmin(int a,int b,int c)
{
return min(a,min(b,c));
}
int main()
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(dp,0,sizeof(dp));
scanf("%s",a);
scanf("%s",b);
int i,j;
dp[0][0]=0;
for(i=1;i<=strlen(a);i++)
{
dp[i][0]=i;//边界
}
for(j=1;j<=strlen(b);j++)
{
dp[0][j]=j;
}
for(i=1;i<=strlen(a);i++)
{
for(j=1;j<=strlen(b);j++)
{
if(a[i-1]==b[j-1])dp[i][j]=dp[i-1][j-1];//不用转换的情况 注意i,j的含义以及下标是否要-1
else dp[i][j]=mmin(
dp[i-1][j-1]+1,//编辑
dp[i][j-1]+1,//插入 因为是在a[i]插入了一个与b[j]相同的字符,所以这里认为a串第i个之前与b串第j-1个之前的字符经过dp[i][j-1]次操作 匹配了,只需要再增加一次添加操作即可
dp[i-1][j]+1//删除 同理
);
}
}
cout<<dp[strlen(a)][strlen(b)]<<endl;
return 0;
}
来源:https://www.cnblogs.com/lipoicyclic/p/12273012.html