题目分析:将一个字符串变成另外一个字符串所用的最少操作数,每次只能增加、删除或者替换一个字符。
解题思路:
设A[i-1][j-1]表示一个从长为i - 1的字符串str1变为长为j - 1的字符串str2的最短距离。str1转换为str2的过
程主要涉及以下三种情况:
1)替换:将str1中的某个字符替换为str2中的某个字符串,使其变换为接近str2的字符串;
2)增加:在str1字符串后添加一个字符,使其变换为接近str2的字符串;
3)删除:在str1字符串中删除一个字符,使其变换为接近str2的字符串。
动态规划求解:
替换:A[i][j] = (A[i - 1][j - 1] + (str1[i - 1] == str2[j - 1] ? 0 : 1), 此时需考虑str[i - 1] == str2[j - 1];
增加:A[i][j] = (A[i][j - 1] + 1),此时str[i - 1] != str2[j - 1];
删除:A[i][j] = (A[i][j - 1] + 1);此时str[i - 1] != str2[j - 1]。
综上,具体情况主要分两种情况:两个字符相等,和两个字符不相等情况。递推公式如下:
1)当a == b,A[i][j] = min(A[i - 1][j] + 1,A[i][j - 1] + 1,A[i-1][j-1])
2)当a != b, A[i][j] = min(A[i - 1][j] + 1,A[i][j - 1] + 1,A[i-1][j-1] + 1)
class Solution
{
public:
int minDistance(string word1, string word2)
{
int m = word1.length();
int n = word2.length();
// 定义动态规划所需数组
int dp[m + 1][n + 1];
// 初始化第一列元素
for (int i = 0; i <= m; i++)
{
dp[i][0] = i;
}
// 初始化第一行元素
for (int i = 0; i <= n; i++)
{
dp[0][i] = i;
}
// 中间部分处理
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
//增加操作,str1a变成str2后,再加上b得到str2b
int insert = dp[i][j-1] + 1;
//删除操作,str1a删除a后,再由str1变为str2b
int delet = dp[i-1][j] + 1;
//替换操作,先由str1变为str2,然后str1a的a替换为b,得到str2b
int replace = dp[i-1][j-1] + (word1[i - 1] == word2[j - 1] ? 0 : 1);
//取三个最小值
dp[i][j] = min(replace, min(insert, delet));
}
}
// 返回最短的边界距离
return dp[m][n];
}
};