最小编辑距离问题
问题描述
给你两个单词
word1
和word2
, 请返回将word1
转换成word2
所使用的最少操作数。你可以对一个单词进行如下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
这是典型的动态规划问题,因为 word 1 和 word 2 可以划分为子问题,而且子问题与原问题有类似的解结构。
状态定义
dp[i][j]
定义为 word1
的前 i
个字符到 word2
的前 j
个字符的最小操作距离。
状态转移
假设当前处理的子字符串分别为 s1
、s2
-
s1 与 s2 的末尾字符相同
dp[i][j] = dp[i-1][j-1]
-
s1 与s2 的末尾字符不相同
-
(删)删除s1 的末尾字符(假设 s1 的前 i-1 个字符和 s2 的前 j 个字符具有高度相似性)
dp[i][j] = dp[i-1][j]+1
-
(插)在 s1 的末尾插入一个字符与 s2 末尾字符相同(假设s1 的前 i 个字符和 s2 的前 j-1 个字符具有高度相似性)
dp[i][j] = dp[i][j-1]+1
-
(改)将 s1 的末尾字符替换为与 s2 末尾字符相同的字符(假设 s1 的前 i-1 个字符与 s2 的前 j-1 个字符具有高度相似性)
dp[i][j] = dp[i-1][j-1]+1
-
边界条件
dp[0][0] = 0
dp[i][0] = i
dp[0][j] = j
状态转移方程
if(s1[i-1] == s2[j-1]) dp[i][j] = dp[i-1][j-1];
else dp[i][j] = 1 + min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]);
代码实现
#include <iostream>
#include <string>
using namespace std;
string s1, s2;
int dp[20][20];
int MED(string s1, string s2)
{
memset(dp, 0, sizeof(dp));
for (int i = 0; i <= s1.length(); i++)
dp[i][0] = i;
for (int i = 0; i <= s2.length(); i++)
dp[0][i] = i;
for (int i = 1; i <= s1.length(); i++)
{
for (int j = 1; j <= s2.length(); j++)
{
if (s1[i - 1] == s2[j - 1])
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = 1 + min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
}
}
return dp[s1.length() - 1][s2.length() - 1];
}
int main()
{
s1 = "intention";
s2 = "execution";
cout << MED(s1, s2) << endl;
}