1072: 编辑距离

时间限制(普通/Java):1000MS/10000MS 内存限制:65536KByte
这道题的数据量挺大的,先给出我第一次提交的代码,结果超时。
描述
假设字符串的基本操作仅为:删除一个字符、插入一个字符和将一个字符修改成另一个字符这三种操作。
我们把进行了一次上述三种操作的任意一种操作称为进行了一步字符基本操作。
下面我们定义两个字符串的编辑距离:对于两个字符串a和b,通过上述的基本操作,我们可以把a变成b或b变成a,那么字符串a变成字符串b需要的最少基本字符操作步数称为字符串a和字符串b的编辑距离。
例如:a="ABC",b="CBCD",则a与b的编辑距离为2。
你的任务就是:编一个快速的程序来计算任意两个字符串的编辑距离。
输入
输入包含多组测试数据。每组测试数据一行,为字符串A和字符串B。
字符串的长度不大于1024,且全为字母。
输出
编辑距离。
样例输入
ABC CBCD
样例输出
2
提示
我相信动态规划算法能解决这题,因为我就是这样做的。^_^
题目来源
解析:
首先定义这样一个函数——dp(i, j),它表示第一个字符串的长度为i的子串到第二个字符串的长度为j的子串的编辑距离。
显然可以有如下动态规划公式:
- if i == 0 且 j == 0,dp(i, j) = 0
- if i == 0 且 j > 0,dp(i, j) = j
- if i > 0 且j == 0,dp(i, j) = i
- if i ≥ 1 且 j ≥ 1 ,dp(i, j) == min{ dp(i-1, j) + 1, dp(i, j-1) + 1, dp(i-1, j-1) + f(i, j) },当第一个字符串的第i个字符不等于第二个字符串的第j个字符时,f(i, j) = 1;否则,f(i, j) = 0。
#include <iostream>
#include <string>
using namespace std;
int dp[1025][1025];
int main()
{
string a,b;
int aLen,bLen;
while(cin>>a>>b)
{
aLen = a.size();
bLen = b.size();
for(int i = 0 ; i <= aLen ; i++)
{
dp[i][0] = i;
}
for(int j = 0 ; j<=bLen ; j++)
{
dp[0][j] = j;
}
for(int i = 1 ; i <= aLen ; i++)
{
for(int j = 1 ; j <= bLen ; j++)
{
dp[i][j] = min(dp[i-1][j],dp[i][j-1])+1;
dp[i][j] = min(dp[i][j],dp[i-1][j-1]+(a[i-1]==b[j-1]?0:1));
}
}
cout<<dp[aLen][bLen]<<endl;
}
return 0;
}
猜想string内部比char[]占用了一些时间,因为string要自动维持可变长度,这只是个人自己的一点猜想,没有任何考证,也没有去查阅相关资料,太懒!希望有懂得人留言告诉我一下。
#include <iostream>
#include <cstring>
using namespace std;
int dp[1025][1025];
char a[1025];
char b[1025];
int main()
{
int aLen,bLen;
while(cin>>a>>b)
{
aLen = strlen(a);
bLen = strlen(b);
for(int i = 0 ; i <= aLen ; i++)
{
dp[i][0] = i;
}
for(int j = 0 ; j<=bLen ; j++)
{
dp[0][j] = j;
}
for(int i = 1 ; i <= aLen ; i++)
{
for(int j = 1 ; j <= bLen ; j++)
{
dp[i][j] = min(dp[i-1][j],dp[i][j-1])+1;
dp[i][j] = min(dp[i][j],dp[i-1][j-1]+(a[i-1]==b[j-1]?0:1));
}
}
cout<<dp[aLen][bLen]<<endl;
}
return 0;
}