I have two strings, say str1
and str2
. I need to convert the first one to the second one while making the least number of edits. This is what is called as Edit Distance. Suppose we need to convert Sunday
to Saturday
. The first letter is the same, and the last three are the same as well, so it boils down to converting un
to atur
. This can be done in 3 steps - Replace 'n' with 'r', insert 't', insert 'a'. That gives the edit distance as 3. Following is the program to find out the edit distance -
// A Dynamic Programming based C++ program to find minimum
// number operations to convert str1 to str2
#include<bits/stdc++.h>
using namespace std;
// Utility function to find minimum of three numbers
int min(int x, int y, int z)
{
return min(min(x, y), z);
}
int editDistDP(string str1, string str2, int m, int n)
{
// Create a table to store results of subproblems
int dp[m+1][n+1];
// Fill d[][] in bottom up manner
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++)
{
// If first string is empty, only option is to
// isnert all characters of second string
if (i==0)
dp[i][j] = j; // Min. operations = j
// If second string is empty, only option is to
// remove all characters of second string
else if (j==0)
dp[i][j] = i; // Min. operations = i
// If last characters are same, ignore last char
// and recur for remaining string
else if (str1[i-1] == str2[j-1])
dp[i][j] = dp[i-1][j-1];
// If last character are different, consider all
// possibilities and find minimum
else
dp[i][j] = 1 + min(dp[i][j-1], // Insert
dp[i-1][j], // Remove
dp[i-1][j-1]); // Replace
}
}
return dp[m][n];
}
// Driver program
int main()
{
// your code goes here
string str1 = "sunday";
string str2 = "saturday";
cout << editDistDP(str1, str2, str1.length(), str2.length());
return 0;
}
While this returns the correct result, I also need to output the exact steps of conversion, i.e. something like
Sunday -> Surday -> Sturday -> Saturday.
How do I do the second step?
答案 0 :(得分:2)
创建dp
表格后,您可以按照创建表格的方式,将(m, n)
改为(0, 0)
。
这是一个打印修改的解决方案,但您也可以返回修改矢量。
int editDistDP(string str1, string str2)
{
int m = str1.length();
int n = str2.length();
int dp[m + 1][n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0) {
dp[i][j] = j;
} else if (j == 0) {
dp[i][j] = i;
} else if (str1[i-1] == str2[j-1]) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = 1 + min3(dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]);
}
}
}
i = m; j = n;
while (i && j) {
if (i == 0) {
cout << "insert " << str2[j - 1] << endl;
j--;
} else if (j == 0) {
cout << "remove " << str1[i - 1] << endl;
i--;
} else if (str1[i - 1] == str2[j - 1]) {
i--; j--;
} else {
int k = imin3(dp[i][j - 1],
dp[i - 1][j],
dp[i - 1][j - 1]);
if (k == 2) {
cout << "replace " << str1[i - 1]
<< " with " << str2[j - 1] << endl;
i--; j--;
} else if (k == 1) {
cout << "remove " << str1[i - 1] << endl;
i--;
} else {
cout << "insert " << str2[j - 1] << endl;
j--;
}
}
}
return dp[m][n];
}
这里,imin3
是一个函数,它返回列表中最小元素的索引0,1或2。