【字符串+DP】POJ 4007:计算字符串距离

总时间限制: 
1000ms 
内存限制: 
65536kB
描述
对于两个不同的字符串,我们有一套操作方法来把他们变得相同,具体方法为:
  1. 修改一个字符(如把“a”替换为“b”)
  2. 删除一个字符(如把“traveling”变为“travelng”)

比如对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g”的方式来达到目的。无论增加还是减少“g”,我们都仅仅需要一次操作。我们把这个操作所需要的次数定义为两个字符串的距离。 
给定任意两个字符串,写出一个算法来计算出他们的距离。
输入
第一行有一个整数n。表示测试数据的组数,
接下来共n行,每行两个字符串,用空格隔开。表示要计算距离的两个字符串
字符串长度不超过1000。
输出
针对每一组测试数据输出一个整数,值为两个字符串的距离。
样例输入
3
abcdefg  abcdef
ab ab
mnklj jlknm
样例输出
1
0
4

这道题的时间限制是1秒,但处理的字符串长度可能达到1000,所以如果使用递归的话,则必然超时。因此,可采用动态规划的方法,构造一个二维数组,数组的“长”和“宽”分别是两个字符串的长度。

以题中的一个例子举例,字符串a=“jlknm”,b=“mnklj”,则可构造一个6×6的二维数组array,并将二维数组的第一行和第一列初始化为如下,因为一个空字符串和任意一个字符串的距离始终为该字符串的长度。


用两层for循环遍历两个字符串a、b(i和j从1开始取值),对比每一个字符a[i-1]和b[j-1],若两个字符相等,即a[i-1] == b[j-1],则不增加距离,因此对应的数组array[i][j]=array[i-1][j-1];若两个字符不相等,则可删除a[i-1]这个字符、删除b[j-1]这个字符,或修改a[i-1]使它与b[i-1]相等。array[i][j]取这三种方法的最小值。选择修改,则array[i][j] = 1 + array[i-1][j-1],若选择删除a[i-1],则array[i][j] = 1 + array[i-1][j],若选择删除b[i-1],则array[i][j] = 1 + array[i][j-1]。运用这个方法,可将二维数组填满,如下图所示。


最后,取这个数组的最后一个元素4,即为答案。

/*样例输入
3
abcdefg  abcdef
ab ab
mnklj jlknm
样例输出
1
0
4*/
#include
#include
#include
#include
#define N 1001
using namespace std;
 
int dp[N][N];
char str1[N],str2[N];
int mymin(int a,int b,int c)
{
	if(a<=b&&a<=c) return a;
	else if(b<=a&&b<=c) return b;
	else return c;
}
int main()
{
	int n;
	int i,j;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%s%s",str1,str2);
		int len1=strlen(str1);
		int len2=strlen(str2);
		for(i=0;i<=len1;i++) dp[i][0]=i;
		for(i=0;i<=len2;i++) dp[0][i]=i;
		for(i=1;i<=len1;i++)
		{
			for(j=1;j<=len2;j++)
			{
				if(str1[i-1]==str2[j-1]) dp[i][j]=dp[i-1][j-1];
				else
				{
					dp[i][j]=mymin(dp[i-1][j],dp[i-1][j-1],dp[i][j-1])+1;
				}
			}
		}
		printf("%d\n",dp[len1][len2]);
	}
	return 0;
}


你可能感兴趣的:(百练,dp,字符串距离)