- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
对于两个不同的字符串,我们有一套操作方法来把他们变得相同,具体方法为:
- 修改一个字符(如把“a”替换为“b”)
- 删除一个字符(如把“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<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string.h>
#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;
}