编辑距离

问题:设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.

依次运算,得到最后一行最后一列即为最优解。




你可能感兴趣的:(算法,动态规划,编辑距离)