编辑距离

题目:

假设,字符串仅有三个基本操作:删除一个字符、插入一个字符和将一个字符修改成另一个字符。

基本的字符操作:进行了一次上述三种操作的任意一种操作

两个字符串的编辑距离的定义:通过上述的基本操作,我们可以把字符串a变成字符串b,所需要的最少基本字符操作次数

举例:snowy  与 sunny 的编辑距离为3

我们的任务:计算任意两个字符串的编辑距离

状态转移方程

d[ i ][ j ]:表示把源文本串X的前i个字符串转换为目标串Yj个字符串的最小代价

d[ i ][ j ] = min (d[i - 1][j - 1] + cost ,  d[i - 1][j]+1, d[i][j-1]+1)

其中,当 X[i] = Y[j]时,cost = 0。当 X[i]  != Y[j],cost = 1

注意:这三种情况都可以转化成d[ i ][ j ],它们是并列的,写状态转移方程时,所有能转化为d[ i ][ j ]的情况都要考虑到。

简单说明:如果取d[i][j - 1]最小,表示X[1 ~ i] 和 Y[1 ~ j - 1] 已经完全匹配,由于X的i个序列已经全部处理完毕,但是Y还剩一个,我们只需要在往X中添加一个元素Y[j]即可,此时X的前i个和Y的前j个就全部相等了

迭代代码

#include <iostream>
using namespace std;
const int MaxLen = 20;

//char X[] = " snowy"; 
//char Y[] = " sunny";  

char X[] = " interestingly"; 
char Y[] = " bioinformatics";  

int d[MaxLen][MaxLen] = {{0}};

void PrintD(int lenX,int lenY)
{
	for (int i = 0;i <= lenX;i++)
	{
		for (int j = 0;j <= lenY;j++)
		{
			cout<<d[i][j]<<" ";
		}
		cout<<endl;
	}
}


int Min(int x,int y,int z)
{
	if (x < y)
	{
		if (x < z)  //  x < y
		{
			return x;
		}
		else     // z < x < y
		{
			return z;
		}
	}
	else
	{
		if (y < z)  //x > y
		{
			return y;
		}
		else        //x > y y >= z
		{
			return z;
		}
	}
}

// 处理过程中,我们只修改原始字符串,对该字符串增删改
int EditDistance(int lenX,int lenY)
{
	int cost = 0;
	//初始化边界条件
	//X串有内容,Y串没有内容
	for (int i = 1;i <= lenX;i++)
	{
		d[i][0] = i;//X串要变成Y串,每次需要在X串中删除一个字符 
	}

	//X串为空,Y有内容
	for (int j = 1;j <= lenY;j++)
	{
		d[0][j] = j;//X串没内容,X串要变成Y,必须往X串中插入Y[i]
	}

	for (int i = 1;i <= lenX;i++)
	{
		for (int j = 1;j <= lenY;j++)
		{
			if (X[i] == Y[j])
			{
				cost = 0;
			}
			else
			{
				cost = 1;
			}
			int Replace = d[i - 1][j - 1] + cost;
			int Insert = d[i][j - 1] + 1;
			int Del = d[i - 1][j] + 1;
			d[i][j] = Min(Replace,Insert,Del);
		}
	}
	return d[lenX][lenY];
}

int main()
{
	int lenX = strlen(X) - 1;
	int lenY = strlen(Y) - 1;
	cout<<EditDistance(lenX,lenY)<<endl;
	//PrintD(lenX,lenY);
	system("pause");
	return 0;
}

注意一点:上述代码中,无论X[i] 与 Y[j]是否相等,都是进行了删除和添加操作。其实也可以在字符不等时,进行修改删除和添加操作。在字符相等时,不进行任何操作。d[i][j] = d[i - 1][j - 1].

备忘录

#include <iostream>
using namespace std;

const int MaxLen = 20;

/*char X[] = " interestingly";   
char Y[] = " bioinformatics";*/ 

char X[] = " snowy";    
char Y[] = " sunny"; 

int d[MaxLen][MaxLen] = {{0}};


int Min(int x,int y,int z)
{
	if (x < y)
	{
		if (x < z)  //  x < y
		{
			return x;
		}
		else     // z < x < y
		{
			return z;
		}
	}
	else
	{
		if (y < z)  //x > y
		{
			return y;
		}
		else        //x > y y >= z
		{
			return z;
		}
	}
}

// 处理过程中,我们只修改原始字符串,对该字符串增删改
int EditDistance(int i,int j)
{
	int cost = 0;
	if (d[i][j])
	{
		return d[i][j];
	}
	//边界条件
	if (i == 0 && j != 0)
	{
		return d[i][j] = EditDistance(i,j - 1) + 1;//插入代价
	}
	
	if (i != 0 && j == 0)
	{
		return d[i][j] = EditDistance(i - 1,j) + 1;//删除代价
	}
	
	if (!i && !j)
	{
		return 0;
	}

	//正式处理
	if (X[i] == Y[j])
	{
		cost = 0;
	}
	else
	{
		cost = 1;
	}
	int Replace = EditDistance(i - 1,j - 1) + cost; 
	int Insert = EditDistance(i,j - 1) + 1;  
	int Del = EditDistance(i - 1,j) + 1;
	return d[i][j] = Min(Replace,Insert,Del);
}

int main()
{
	cout<<EditDistance(strlen(X) - 1,strlen(Y) - 1)<<endl;
	system("pause");
	return 0;
}

递归暴力

#include <iostream>
using namespace std;

const int MaxLen = 20;

//char X[] = " interestingly";   
//char Y[] = " bioinformatics"; 

char X[] = " snowy";    
char Y[] = " sunny"; 

int Min(int x,int y,int z)
{
	if (x < y)
	{
		if (x < z)  //  x < y
		{
			return x;
		}
		else     // z < x < y
		{
			return z;
		}
	}
	else
	{
		if (y < z)  //x > y
		{
			return y;
		}
		else        //x > y y >= z
		{
			return z;
		}
	}
}

// 处理过程中,我们只修改原始字符串,对该字符串增删改
int EditDistance(int i,int j)
{
	int cost = 0;
	//边界条件
	if (i == 0 && j != 0)
	{
		return j;//插入代价
	}
	
	if (i != 0 && j == 0)
	{
		return i;//删除代价
	}
	
	if (!i && !j)
	{
		return 0;
	}

	//正式处理
	if (X[i] == Y[j])
	{
		cost = 0;
	}
	else
	{
		cost = 1;
	}
	int Replace = EditDistance(i - 1,j - 1) + cost; 
	int Insert = EditDistance(i,j - 1) + 1;  
	int Del = EditDistance(i - 1,j) + 1;
	return Min(Replace,Insert,Del);
	
}

int main()
{
	cout<<EditDistance(strlen(X) - 1,strlen(Y) - 1)<<endl;
	system("pause");
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值