动态规划 - 编辑距离
问题
编辑距离(Edit Distance),是指两个字符串之间,由一个转成另一个所需的编辑操作(替换,插入,删除)的次数。
分析
首先定义函数 editDistance(i,j) ,表示第一个字符串 s1 的长度为 i 的子串到第二个字符串 s2 的长度为 j 的子串的编辑距离。
显然,有以下动态规划公式:
1. 当 i=0 且 j=0 时, editDistance(i,j)=0
2. 当 i=0 且 j>0 时, editDistance(i,j)=j
3. 当 i>0 且 j=0 时, editDistance(i,j)=i
4. 当 i>0 且 j>0 时, editDistance(i,j)=min{editDistance(i-1,j)+1,editDistance(i,j-1)+1,editDistance(i-1,j-1)+f(i,j)},其中当 s1[i]=s2[j] 时,f(i,j)=0;当 s1[i]!=s2[j] 时,f(i,j)=1
实现
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#define N 1000
int min(int num1,int num2,int num3);
int getEditDistance(char *s1,char *s2);
int main(void){
char s1[N],s2[N];
scanf("%s %s",&s1,&s2);
printf("MinEditDistance:%d",getEditDistance(s1,s2));
return 0;
}
int min(int num1,int num2,int num3){
int less=(num1<num2)?num1:num2;
return (less<num3)?less:num3;
}
int getEditDistance(char *s1,char *s2){
int len1=strlen(s1),len2=strlen(s2);
int **distance;
distance=(int **)malloc(sizeof(int *)*(len1+1));
for(int i=0;i<=len1;i++)
distance[i]=(int *)malloc(sizeof(int)*(len2+1));
for(int i=0;i<=len1;i++)
distance[i][0]=i;
for(int j=0;j<=len2;j++)
distance[0][j]=j;
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
if(s1[i-1]==s2[j-1])
distance[i][j]=distance[i-1][j-1];
else{
int deletion=distance[i-1][j]+1;
int insertion=distance[i][j-1]+1;
int substitution=distance[i-1][j-1]+1;
distance[i][j]=min(deletion,insertion,substitution);
}
}
}
int editDistance=distance[len1][len2];
for(int i=0;i<=len1;i++)
free(distance[i]);
free(distance);
return editDistance;
}