问题:错误拼写检查,将字符串T修改为P,并且要求改动次数最少
例子:求出将"hsppay"(T)改成”happy“(P)的最少改动次数
分析:将字符串T改成P,有以下几种操作:
(1)修改:将字符串T的某个字符修改了
(2)删除:T比P要长,如果改成P,某些字符必须删除
(3)增加:T比P要短,如果改成P,要增加某些字符
通过上面三波操作,绝对能把T改成P,并且有很多种方法。
可以先把T完全删除,然后再插入P;也可以把T改成P,多出来的删掉,少的给补上。。。
方法很多,出于效率,我们要选取最小的那一种方案。
设将字符串将字符串T[0]~T[j]修改成P[0]~P[i]的最少改动次数为dp(i,j)
通过上面的分析可以得到
1.当T[j]=P[i]的时候:
(1)保持原状,不修改,不增加,不删除:T[j]都等于P[i]了,还修改个什么劲啊,∴修改次数为D(i-1,j-1)
(2)删除掉T[j](修改一次了,次数+1),∴修改次数为D(i-1,j)+1
(3)在T[j]前增加字符(修改一次了,次数+1),∴修改次数为D(i,j-1)+1
注意:为什么T[j]都等于了P[i],还要删除或修改?
举个例子:T="ha",P="haz"
T[1]=P[2],但是很明显T[1]前要插入字符Z。
∴D(i,j)=min( D(i,j) , D(i-1,j)+1 , D(i,j-1)+1 )
2.当T[j]≠P[i]时
(1)修改:将T[j]改成P[i]。修改次数为D(i-1,j-1)+1
(2)删除:删除掉T[j],修改次数为D(i-1,j)+1
(3)增加:在T[j]前增加字符串,修改次数为D(i,j-1)+1
∴D(i,j)=min( D(i,j)+1 , D(i-1,j)+1 , D(i,j-1)+1 )
代码
#include<stdio.h>
#include<string.h>
#define N 100
#define M 100
int D[M][N];
int min(int a,int b,int c){
if(a<b && a<c) return a;
if(b<a && b<c) return b;
return c;
}
int ASM(char P[],int m,char T[],int n){
int i,j;
for(j=1;j<=n;j++){
D[0][j]=j;
}
for(i=0;i<=m;i++){
D[i][0]=i;
}
for(j=1;j<=n;j++){
for(i=1;i<=m;i++){
if(P[i-1]==T[j-1]){
D[i][j]=min(D[i-1][j-1],D[i-1][j]+1,D[i][j-1]+1);
}else{
D[i][j]=min(D[i-1][j-1]+1,D[i-1][j]+1,D[i][j-1]+1);
}
}
}
return D[m][n];
}
int main(){
char P[]="hsppay";
char T[]="happy";
printf("%d\n",ASM(P,strlen(P),T,strlen(T)));
return 0;
}