动态规划之编辑距离

思考:我们可以从题目中给出的6种操作描述,找到递归式,比如复制操作是i和j都增加1。那么递归式就是c[i][j]=c[i-1][j-1]+cost[COPY]。c[i][j]表示从字符串i复制到字符串j所需要的总代价。其他操作类似。

递归式如下

代码如下

#include <iostream>
using namespace std;
enum {COPY,REPLACE,DELETE,INSERT,TWIDDLE,KILL,ENUM_MAX};//TWIDDLE旋转
struct T
{
   int **c,**op;
   T(int m,int n)
   {
	   c=new int*[m+1];
	   for ( int i=0;i<=m;i++)
	   {
		   c[i]=new int[n+1];
	   }
	   op=new int*[m+1];
	   for ( i=0;i<=m;i++)
	   {
		   op[i]=new int[n+1];
	   }
   }
};
struct T EDIT_DISTANCE(char x[],char y[],int m,int n)
{
	int i,j;
	struct T t(m,n);
	int cost[ENUM_MAX]={-1,1,2,2,-2,1};
	t.c[0][0]=0;
	for ( i=0;i<=m;i++)
	{
		t.c[i][0]=i*cost[DELETE];
		t.op[i][0]=DELETE;
	}
	for (j=0;j<=n;j++)
	{
		t.c[0][j]=j*cost[INSERT];
		t.op[0][j]=INSERT;
	}
	for (i=1;i<=m;i++)
	{
		for (j=1;j<=n;j++)
		{
			t.c[i][j]=0x7fffffff;
			if (x[i]==y[j]&&t.c[i-1][j-1]+cost[COPY]<t.c[i][j])
			{
				t.c[i][j]=t.c[i-1][j-1]+cost[COPY];
				t.op[i][j]=COPY;
			}
			if (x[i]!=y[j]&&t.c[i-1][j-1]+cost[REPLACE]<t.c[i][j])
			{
				t.c[i][j]=t.c[i-1][j-1]+cost[REPLACE];
				t.op[i][j]=REPLACE;
			}
			if (i>=2&&j>=2&&x[i]==y[j-1]&&x[i-1]==y[j]&&t.c[i-2][j-2]+cost[TWIDDLE]<t.c[i][j])
			{
               t.c[i][j]=t.c[i-2][j-2]+cost[TWIDDLE];
			   t.op[i][j]=TWIDDLE;
			}
			if (t.c[i-1][j]+cost[DELETE]<t.c[i][j])
			{
				t.c[i][j]=t.c[i-1][j]+cost[DELETE];
				t.op[i][j]=DELETE;
			}
			if (t.c[i][j-1]+cost[INSERT]<t.c[i][j])
			{
				t.c[i][j]=t.c[i][j-1]+cost[INSERT];
				t.op[i][j]=INSERT;
			}
		}
	}
	for ( i=0;i<=m-1;i++)
	{
		if (t.c[i][n]+cost[KILL]<t.c[m][n])
		{
			t.c[m][n]=t.c[i][n]+cost[KILL];
			t.op[m][n]=i;
		}
	}
	cout<<"c[m][n]="<<t.c[m][n]<<" "<<endl;
	for (i=0;i<=m;i++)
	{
		for ( j=0;j<=n;j++)
		{
			cout<<t.c[i][j]<<"  ";
		}
		cout<<endl;
	}
	cout<<endl;
	for (i=0;i<=m;i++)
	{
		for (int j=0;j<=n;j++)
		{
			cout<<t.op[i][j]<<"  ";
		}
		cout<<endl;
	}
	cout<<endl;
	return t;
}
void OP_SEQUENCE(struct T t,int i,int j)
{
	int I,J;
    if(i==0&&j==0)return;
	if (t.op[i][j]==COPY||t.op[i][j]==REPLACE)
	{
        I=i-1;
		J=j-1;
	}
	else if(t.op[i][j]==TWIDDLE)
	{
		I=i-2;
		J=j-2;
	}
	else if (t.op[i][j]==DELETE)
	{
		I=i-1;
		J=j;
	}
	else if (t.op[i][j]==INSERT)
	{
		I=i;
		J=j-1;
	}
	else
	{
		I=t.op[i][j];
		J=j;
		t.op[i][j]=KILL;
	}
	OP_SEQUENCE(t,I,J);
	cout<<t.op[i][j]<<" ";
}
void main()
{
	char x[] = " algorithm";
	char y[] = " altruistic";
	int m = strlen(x), n = strlen(y);
	struct T t=EDIT_DISTANCE(x,y,m,n);
	OP_SEQUENCE(t,m,n);
}

总结: 这个和求LCS类似。运行时间为O(mn)。理解了LCS这个应该没问题。还有注意初始化和最后操作kill即可。

动态规划之编辑距离

时间: 2024-10-07 13:48:06

动态规划之编辑距离的相关文章

动态规划:编辑距离和通配符匹配

编辑距离指通过修改,删除,添加.使得两个字符串能够相同所需要操作的次数. edit(i,j) if S1[i]==S2[j] temp=0; else temp=1; edit(i,j)=min(A[i-1][j-1]+temp,A[i-1][j]+1,A[i][j-1]+1); edit(i,j)=min(A[i-1][j-1]+temp,A[i-1][j]+1,A[i][j-1]+1);公式可以理解成, 如果由S1或者增加,删除,替换一次,同两个字符串的推前一个的编辑距离比较.最小值即编辑距

动态规划求解编辑距离

一.动态规划算法 动态规划算法通常基于一个递推公式及一个或多个初始状态.当前问题的解将由上一次子问题的解推出.使用动态规划来解题只需要多项式复杂度,因此它比 回溯法.暴力法要快.首先,我们要找到某个状态的最优解,然后在它的帮助下,找到下一个状态的最优解.要做的是抽象出动态规划的状态和状态转移方程(递推公式). 二.编辑距离 1.问题描述 设A和B是2个字符串.要用最少的字符操作将字符串A转换为字符串B.这里所说的字符操作包括: (1)删除一个字符; (2)插入一个字符: (3)将一个字符改为另一

动态规划——最短编辑距离

编辑距离是指两个字串之间,从一个转成另一个所需要的最少编辑操作次数,许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符. 问题     给定两个字符串S1和S2,求S2和S1的编辑距离,即至少需要经过多少步编辑操作才可以将S1变成S2. 分析     定义“状态” edit[i][j],表示将S1的长度为i的前缀S1[1...i]到S2的长度为j的前缀S2[1....j]的编辑距离.则显然有: if (i == 0 && j == 0) edit[i][j] = 0;

动态规划--P2758 编辑距离

*传送 动态规划最主要确定状态和转移方程,所以我的思路如下: 1.定义状态: 确定dp(i,j)代表字符串A的前i个字符(包括第i个)变为字符串B的前j个(包括第j个)需要多少步.而dp[l1][l2]就是我们所要找的答案. 2.转移方程: *删:dp(i-1,j)+1 //字符串A的前i-1个字符变为字符串B的前j个需要多少步 [把字符串的第i个字符(最后一个)删除了],删除需要一步因此加1 *添:dp(i,j-1)+1 //将B[j]字符加在A字符串的最后面即添加,同样可以理解为将B[j]字

poj3356 AGTC(经典DP最小编辑距离)

题目意思: 给出两个字符串X,Y,求出从X-->Y的最小操作次数,只可以删除,添加,修改一个字符. http://poj.org/problem?id=3356 题目分析: /** *x,y:是字符串 *动态规划最小编辑距离, *dp[i][j]表示取x的前i个字符和y的前j个字符操作的最小次数. *dp[0][j]=j:取x的前0个字符和y的前j个字符操作的 *最小次数为(j),只能添加到x * *dp[i][0]=i:取x的前i个字符和y的前0个字符操作的 *最小次数为(i),只能删除x *

Minimum Edit Distance with Dynamic Programming

1. Question / 实践题目 2. Analysis / 问题描述 3. Algorithm / 算法描述 3.1. Substitution 3.2. Insertion 3.3. Deletion 3.4. Sepcial Cases 3.5. Equation 4. Fill the table / 填表 4.1. Dimention 4.2. Range 4.3. Order 4.4. Related Code 5. Show Me the Code / 完整代码 6. T(n)

编辑距离 动态规划

动态规划经常被用来作为这个问题的解决手段之一. 整数 Levenshtein距离(字符串 str1[1..m], 字符串 str2[1..n]) //声明变量, d[i , j]用于记录str1[1...i]与str2[1..j]的Levenshtein距离 int d[0..m, 0..n] //初始化 for i from 0 to m d[i, 0] := i for j from 0 to n d[0, j] := j //用动态规划方法计算Levenshtein距离 for i fro

两个字符串的编辑距离-动态规划方法

两个字符串的编辑距离-动态规划方法[转载] 概念 字符串的编辑距离,又称为Levenshtein距离,由俄罗斯的数学家Vladimir Levenshtein在1965年提出.是指利用字符操作,把字符串A转换成字符串B所需要的最少操作数.其中,字符操作包括: 删除一个字符     a) Delete a character 插入一个字符     b) Insert a character 修改一个字符     c) Replace a character 例如对于字符串"if"和&qu

8.动态规划(1)——字符串的编辑距离

动态规划的算法题往往都是各大公司笔试题的常客.在不少算法类的微信公众号中,关于“动态规划”的文章屡见不鲜,都在试图用最浅显易懂的文字来描述讲解动态规划,甚至有的用漫画来解释,认真读每一篇公众号推送的文章实际上都能读得懂,都能对动态规划有一个大概了解. 什么是动态规划?通俗地理解来说,一个问题的解决办法一看就知道(穷举),但不能一个一个数啊,你得找到最优的解决办法,换句话说题目中就会出现类似“最多”.“最少”,“一共有多少种”等提法,这些题理论上都能使用动态规划的思想来求解.动态规划与分治方法类似