编辑距离

/*
编辑距离:问题介绍:对于编辑距离的问题基本上是对于序列Xi,转换为序列Yj,这个过程的话可以涉及到中间序列Z,包含的操作有插入,删除,替换,复制,交换,终止
对于各个的操作步骤不在解释,可参见算法导论p218,对应介绍,这里给定的一个定义就是编辑距离的定义:如何让从序列Xi到Yj的转换的开销变得最小;

  思路:转换的开销我们记做c[i][j],表示从Xi到Yj 的开销。我们可以认为的话对于上面的六种操作分成六个情况讨论,一般情况我们解决使用动态规划的话,从最终的子结构开始进行讨论那么:1.当复制操作的时候,有两个序列的
最后一个是相同的即Xi==Yj,相应的存在的情况就是c[i][j]=c[i-1][j-1]+cost(复制),由于复制的话相应的对应最后一个的必定相等,开销为各自减一(复制会加一)的对应开销,加上复制一次的开销;2当是替换的时候
由于是把X中对应的位置的换成Yj中的,那么Xi中的序列要往前加一,Yj也是的,只是Yj的最后一个元素是用需要替换的元素进行操作替换而已,对应开销是c[i][j]=c[i-1][j-1]+cost(替换);对应下标解释和情况1一样;
3.当时交换的时候必须要满足,Xi中以及Yj中的下标个数是大于等于2的,否则如何交换?此外是由于交换是如此操作Y[j-1]=X[i],Y[j]=X[i-1],相应的子问题往前推2个得到的开销式子为:c[i][j]=c[i-2][j-2]+cost(交换);4
.删除操作的话是把Xi中的元素指标往后移动一个,而Yj中的不懂,对应的对于二者都木有任何的限制,对应的可以知道的就是c[i][j]=c[i-1][j]+cost(删除);5.插入:插入的开销主要是Xi不懂下标,Yj的下标移动一个,加入元素,开销
c[i][j]=c[i][j-1]+cost(插入);6.终止:终止的话必定是达到下标界限,书上的下标界限是m,n,对于Xi执行到Yn的话,必定是在Xi的i位置执行一次终止,那么就得到Yn,我们需要的是最小的开销,那么就是可以如此的进行表示
c[m][n]=min(c[i][n])+cost(终止);

  注意:对于特殊的情况当Xi,Y0的时候,意思是,序列Xi删除,知道Yj为全0,还有就是X0,Yj的时候就是一直在插入
*/
#include <iostream>
#include <string>
using namespace std;
#define N 11
#define C 1//各个开销大小
#define R 1
#define D 1
#define I 1
#define T 1
#define K 1
//这里交换的话,交换字符吧
struct distance_cost
{
	int m,n;//实际的下标,你妹!!!这里下标溢出!!
	int c[N+1][N+1];//总开销
	char op[N+1][N+1];//用字符记录操作,c:复制,d:删除,i:插入,t:交换,k:终止
	string x,y;//x,y的长度要保证
	distance_cost(int m_num,int n_num):m(m_num),n(n_num)
	{	
		cout<<"input x and y  "<<endl;
		cin>>x>>y;
		if (x.size()!=m||y.size()!=n)
		{
			cerr<<"length is no ok !"<<endl;
			return ;
		}
		for (int i=0;i<=N;++i)
			for (int j=0;j<=N;++j)
			{
				c[i][j]=0xfffffff;
				op[i][j]=' ';
			}
	}
	void edit_distance();
	void print();
};

void distance_cost::edit_distance()
{
	int i,j;
	for (i=1;i<=m;++i)
	{
		c[i][0]=i*D;//删除i次
		op[i][0]='d';//记录操作
	}
	for (i=1;i<=n;++i)
	{
		c[0][i]=i*I;//插入次数
		op[0][i]='i';
	}
	for (i=1;i<=m;++i)
		for (j=1;j<=n;++j)
		{
			if (x[i]==y[j])
			{
				c[i][j]=c[i-1][j-1]+C;
				op[i][j]='c';
			}
			if(x[i]!=y[j]&&c[i][j]>c[i-1][j-1]+R)
			{
				c[i][j]=c[i-1][j-1]+R;
				op[i][j]='r';
			}
			if (i>=2&&j>=2&&x[i-1]==y[j]&&x[i]==y[j-1]&&c[i][j]>c[i-2][j-2]+T)
			{
				c[i][j]=c[i-2][j-2]+T;
				op[i][j]='t';
			}
			if (c[i][j]>c[i-1][j]+D)
			{
				c[i][j]=c[i-1][j]+D;
				op[i][j]='d';
			}
			if (c[i][j]>c[i][j-1]+I)
			{
				c[i][j]=c[i][j-1]+I;
				op[i][j]='i';
			}
		}
		for (i=0;i<m;++i)
		{
			if(c[m][n]>c[i][n]+K)
			{
				c[m][n]=c[i][n]+K;
				op[m][n]='k';
			}
		}
}

void distance_cost::print()
{
	for (int i=1;i<=m;++i)
		for (int j=1;j<=n;++j)
		{
			cout<<op[i][j]<<" ";
		}
	cout<<endl;
}

int main()
{
	distance_cost d_st(9,10);
	d_st.edit_distance();
	d_st.print();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值