【题目描述】
设 A 和 B 是两个字符串。我们要用最少的字符操作次数,将字符串 A 转换为字符串 B。这里所说的字符操作共有三种:
- 删除一个字符;
- 插入一个字符;
- 将一个字符改为另一个字符。
A,B 均只包含小写字母。
【输入】
第一行为字符串 A;第二行为字符串 B;字符串 A,B 的长度均小于 2000。
【输出】
只有一个正整数,为最少字符操作次数。
样例输入
sfdqxbw
gfdgw
样例输出
4
解题思路
这个题目的思路有点难找……
先一点点拆分,如果我要找的是一个字符串 a 和一个字符串 b,他们的长度分别为 lena,lenb,首先输入两个很短的字符串,其中 lena 为1,而 lenb 为 0,此时要删除一个字母,操作数为 1;如果输入的字符串分别为:k、k,这样相等的字符串,操作数为 0……
这里用的动态规划是二维 dp 数组,dp[i][j] 中的 i 和 j 分别代表,字符串 a 的第 i 个位置到字符串 b 的第 j 个位置,要转化为相同的需要进行的操作数。
从小处着手,理清思路,然后将对应的位置存入 dp 数组,最终找到答案。
然后要注意的是:dp[i][j] 的值是根据:原先数组里面的值和字符串进行对应操作后的操作数比较大小,将较小值存入。
代码如下:
#include<stdio.h>
#include<string.h>
char a[2005],b[2005];
int f[2005][2005];
//f[i][j]表示字符串 a的第 i位与字符串的第 j位转换完后相同的最少次数
int min(int x,int y)
{
if(x<y)
return x;
else
return y;
}
int main()
{
int lena,lenb,i,j;
scanf("%s",a);
scanf("%s",b);
lena=strlen(a);
lenb=strlen(b);
for(i=1;i<=lena;i++)
{
for(j=1;j<=lenb;j++)
f[i][j]=2005;
}
//初始化的意义是:当字符串 b中没有字母时,相当于字符串 a删除 i个字母
for(i=0;i<=lena;i++)
f[i][0]=i;
for(i=0;i<=lenb;i++)
f[0][i]=i;
//从第二个字母开始判断,因为 f[i][j]已经初始化
for(i=1;i<=lena;i++)
{
for(j=1;j<=lenb;j++)
{
if(a[i-1]==b[j-1])//字母相同的情况
f[i][j]=min(f[i][j],f[i-1][j-1]);
else
{
f[i][j]=min(f[i][j],f[i-1][j]+1);//删除
f[i][j]=min(f[i][j],f[i][j-1]+1);//添加
f[i][j]=min(f[i][j],f[i-1][j-1]+1);//替换
}
}
}
printf("%d",f[lena][lenb]);
}