问题:设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.
依次运算,得到最后一行最后一列即为最优解。