题目描述
设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; }