问题:设A和B是两个字符串,要用最少的字符操作将字符串A转换成字符串B.
这里所说的字符串操作包括:
(1)删除一个字符;
(2)插入一个字符;
(3)将一个字符改为另一个字符;
将字符串A变换成字符串B所用的最少字符操作数成为字符串A到字符串B的编辑距离.
这个问题我们使用动态规划.动态规划的思想和分治法很像,都是将大问题化小,但是不一样的是,动态规划的子问题往往不是独立的,它总是由前一个的最优解来求下一个,因此也就解决了分治法所带来的重叠性问题
下面是代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100
//找出最小值
int mini(int a,int b,int c)
{
int t;
t=a<b?a:b;
return t<c?t:c;
}
int EditDistance(char A[],char B[])
{
int m,n,i,j;
int delet=0,insert=0,change=0;
int Edit[N][N];
int Min=0;
m=strlen(A)+1;
n=strlen(B)+1;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
Edit[i][j]=0;
//初始化Edit[i][0]
for(i=0;i<m;i++)
{
Edit[i][0]=i;
// printf("%3d",Edit[i][0]);
}
printf("\n");
//初始化Edit[0][j]
for(j=0;j<n;j++)
{
Edit[0][j]=j;
//printf("%3d",Edit[0][j]);
}
printf("\n");
for(i=1;i<m;i++)
{
for(j=1;j<n;j++)
{
delet=Edit[i][j-1];
delet+=1;//删除所得
//printf("delete:%d\t",delet);
insert=Edit[i-1][j];
insert+=1;//插入所得
// printf("insert:%d\t",insert);
change=Edit[i-1][j-1];
change+=(A[i-1]!=B[j-1]);//直接改变
// printf("\nchange:%d\n",change);
Edit[i][j]=mini(delet,insert,change);
printf("%3d",Edit[i][j]);
Min=Edit[i][j];
}
printf("\n");
}
return Min;
}
void main()
{
//char *str1;
//char *str2;
char A[N],B[N];
int num;
printf("请输入A,B字符串:\nA:");
//scanf("%s",str1);
gets(A);
printf("B:");
//scanf("%s",str2);
gets(B);
num=EditDistance(A,B);
printf("%d\n",num);
}
我们可以使用使用一个二维数组来存储每一次的结果,用A字符串的个数作为列数,B字符串的个数作为行数,当然每一行每一列都要加一,作为第0行第0列,然后我们就可以初始化如下图所示(假设从fxpimu变到xwrs)
0 f x p i m u
0 0 1 2 3 4 5 6
x 1
w 2
r 3
s 4
可以的看出Edit[i][j]=min{Edit[i][j-1]+1,Edit[i-1][j]+1,Edit[i-1][j-1]+f[i][j]};其中Edit[i][j-1]+1为插入步骤,Edit[i-1][j]+1为删除步骤,Edit[i-1][j-1]+f[i][j]为直接改变,其中如果两个字符串不等则f[i][j]=1,否则为0.
依次运算,得到最后一行最后一列即为最优解。
832

被折叠的 条评论
为什么被折叠?



