14.近似串匹配问题

问题:错误拼写检查,将字符串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;
}

 

 

  • 9
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值