- 描述
-
对于两个不同的字符串,我们有一套操作方法来把他们变得相同,具体方法为:
- 修改一个字符(如把“a”替换为“b”)
- 删除一个字符(如把“traveling”变为“travelng”)
比如对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g”的方式来达到目的。无论增加还是减少“g”,我们都仅仅需要一次操作。我们把这个操作所需要的次数定义为两个字符串的距离。
给定任意两个字符串,写出一个算法来计算出他们的距离。 - 输入
-
第一行有一个整数n。表示测试数据的组数,
接下来共n行,每行两个字符串,用空格隔开。表示要计算距离的两个字符串
字符串长度不超过1000。 - 输出
- 针对每一组测试数据输出一个整数,值为两个字符串的距离。
- 样例输入
-
3 abcdefg abcdef ab ab mnklj jlknm
- 样例输出
-
1 0 4
假设有两个字符串ai,bi;
a1,a2,a3......ai;
b1,b2,b3......bi;
如果ai==bi
那么ai与bi对于编辑距离无贡献,所以dp[i][j]=dp[i-1][j-1]
而如果ai!=bi
那么有3种情况
1.删除ai 那么dp[i][j]=dp[i-1][j]+1
2.删除bi 那么dp[i][j]=dp[i][j-1]+1
3.修改ai或bi的值 那么dp[i][j]=dp[i-1][j-1]+1;
所以状态转移公式可以推出
if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]; else dp[i][j]=min(dp[i][j-1],min(dp[i-1][j-1],dp[i-1][j]))+1;
而对于初始状态,如果a为空字符串,那么a对b的距离为b的长度,反之亦为
所以
for(int i=1;i<=len2;i++){ dp[0][i]=i; } for(int i=1;i<=len1;i++){ dp[i][0]=i; }
初始还dp数组
下面是完整代码
#include <iostream> #include<string> #include<string.h> #include<stdio.h> using namespace std; const int maxn=1010; int dp[maxn][maxn]; int main() { int n; scanf("%d",&n); while(n--){ //freopen("in.txt","r",stdin); string a,b; cin>>a>>b; int len1=a.length(); int len2=b.length(); memset(dp,0,sizeof(dp)); for(int i=1;i<=len2;i++){ dp[0][i]=i; } for(int i=1;i<=len1;i++){ dp[i][0]=i; } for(int i=1;i<=len1;i++){ for(int j=1;j<=len2;j++){ if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]; else dp[i][j]=min(dp[i][j-1],min(dp[i-1][j-1],dp[i-1][j]))+1; } } cout<<dp[len1][len2]<<endl; } return 0; }