问题描述:
把两个字符串变成相同的三个基本操作定义如下:
1. 修改一个字符(如把a 变成b)
2. 增加一个字符(如abed 变成abedd)
3. 删除一个字符(如jackbllog 变成jackblog)
针对于jackbllog 到jackblog 只需要删除一个或增加一个l 就可以把两个字符串变为相同。把这种操作需要的最小次数定义为两个字符串的编辑距离L。编写程序计算指定文件中字符串的距离。输入两个长度不超过512 字节的ASCII 字符串,在屏幕上输出字符串的编辑距离。
输入样例:
输入:
Hello world!
Hello word!
输出:
1
思路:
DP问题:具体思路 两个字符串的编辑距离-动态规划方法
用 dp[i][j] 表示到str1的第i个字符与str2的第j个字符的编辑距离,可以得到如下的动态规划方程:
其中,
首先我们令word1和word2分别为:michaelab和michaelxy
- dis[0][0]表示word1和word2都为空的时候,此时他们的Edit Distance为0。
- dis[0][j]就是word1为空,word2长度为j的情况,此时他们的Edit Distance为j,也就是从空,添加j个字符转换成word2的最小Edit Distance为j
- 同理dis[i][0]就是,word1长度为i,word2为空时,word1需要删除i个字符才能转换成空,所以转换成word2的最小Edit Distance为i
- 对于上面例子最后一位:如果b==y, 那么:dis[i][j] = dis[i-1][j-1]。
如果b!=y,那么:添加:也就是在michaelab后面添加一个y,那么word1就变成了michaelaby,此时 dis[i][j] = 1 + dis[i][j-1];删除:也就是将michaelab后面的b删除,那么word1就变成了michaela,此时dis[i][j] = 1 + dis[i-1][j];替换:也就是将michaelab后面的b替换成y,那么word1就变成了michaelay,此时dis[i][j] = 1 + dis[i-1][j-1];
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int N = 10010;
int dp[N][N];
int calculateStrDistance(string sA, string sB)
{
int lA = sA.length(), lB = sB.length();
//边界
for (int i = 0; i <= lA; ++i)
{
dp[i][0] = i;
}
for (int j = 0; j <= lB; ++j)
{
dp[0][j] = j;
}
/*求中间的编辑距离值*/
for (int i = 1; i <= lA; ++i)
{
for (int j = 1; j <= lB; ++j)
{
int flag = 0;
//字符串从0开始存储
if (sA[i - 1] != sB[j - 1])
{
flag = 1;
}
//状态转移方程
dp[i][j] = min(dp[i - 1][j - 1] + flag, min(dp[i - 1][j] + 1, dp[i][j - 1] + 1));
}
}
return dp[lA][lB];
}
int main()
{
string sA, sB;
getline(cin, sA);
getline(cin, sB);
cout << calculateStrDistance(sA, sB) << endl;
return 0;
}