This is a classic problem of Dynamic programming. We define the state to being the minimum number of dp[i][j]
operations to convert to word1[0..i - 1]
word2[0..j - 1]
. The state equations has the cases:the boundary case and the. Note that in the above notations, both and take i
j
values starting from 1
.
For the boundary case, that's, to convert a string to an empty string, it's easy-to-see that the mininum number of opera tions to convert word1[0..i - 1]
to ""
requires at least i
operations (deletions). In fact, the boundary case is simply:
dp[i][0] = i
;
dp[0][j] = j
.
Now let's move on to the general case, that's, convert a non-empty to word1[0..i - 1]
another non-empty word2[0..j - 1]
. Well, let's try-to-break this problem-to-smaller problems (sub-problems). Suppose we have already known how to convert word1[0..i - 2]
word2[0..j - 2]
to, which is dp[i - 1][j - 1]
. Now let ' s consider word[i - 1]
and word2[j - 1]
. If They is euqal, then no more operation is needed and dp[i][j] = dp[i - 1][j - 1]
. Well, what if they is not equal?
If They is not equal, we need to consider three cases:
- Replace
word1[i - 1]
by word2[j - 1]
( dp[i][j] = dp[i - 1][j - 1] + 1 (for replacement)
);
- Delete
word1[i - 1]
and word1[0..i - 2] = word2[0..j - 1]
( dp[i][j] = dp[i - 1][j] + 1 (for deletion)
);
- Insert to and
word2[j - 1]
word1[0..i - 1]
word1[0..i - 1] + word2[j - 1] = word2[0..j - 1]
( dp[i][j] = dp[i][j - 1] + 1 (for insertion)
).
Make sure your understand the subtle differences between the equations for deletion and insertion. For deletion, we is actually converting word1[0..i - 2]
to word2[0..j - 1]
, which costs dp[i - 1][j]
, and then deleting the word1[i - 1]
, which costs c15/>. The case was similar for insertion.
Putting these together, we now have:
dp[i][0] = i
;
dp[0][j] = j
;
dp[i][j] = dp[i - 1][j - 1]
, if word1[i - 1] = word2[j - 1]
;
dp[i][j] = min(dp[i - 1][j - 1] + 1, dp[i - 1][j] + 1, dp[i][j - 1] + 1)
, otherwise.
The above state equations can is turned into the following code directly.
1 classSolution {2 Public:3 intMindistance (stringWord1,stringWord2) { 4 intm = Word1.length (), n =word2.length ();5vector<vector<int> > dp (M +1, vector<int> (n +1,0));6 for(inti =1; I <= m; i++)7dp[i][0] =i;8 for(intj =1; J <= N; J + +)9dp[0][J] =J; Ten for(inti =1; I <= m; i++) { One for(intj =1; J <= N; J + +) { A if(Word1[i-1] = = Word2[j-1]) -DP[I][J] = dp[i-1][j-1]; - ElseDp[i][j] = min (Dp[i-1][j-1] +1, Min (Dp[i][j-1] +1, Dp[i-1][J] +1)); the } - } - returnDp[m][n]; - } +};
Well, we are only need if we have noticed as each time we update dp[i][j]
dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]
. In fact, we need isn't maintain the full m*n
matrix. Instead, maintaing one column is enough. The code can be optimized O(m)
to or O(n)
space, depending on whether you maintain a row or a column of the original m Atrix.
The optimized code is as follows.
1 classSolution {2 Public:3 intMindistance (stringWord1,stringWord2) {4 intm = Word1.length (), n =word2.length ();5vector<int> cur (m +1,0);6 for(inti =1; I <= m; i++)7Cur[i] =i;8 for(intj =1; J <= N; J + +) {9 intPre = cur[0];Tencur[0] =J; One for(inti =1; I <= m; i++) { A inttemp =Cur[i]; - if(Word1[i-1] = = Word2[j-1]) -Cur[i] =Pre; the ElseCur[i] = min (pre +1, Min (Cur[i] +1, Cur[i-1] +1)); -Pre =temp; - } - } + returnCur[m]; - } +};
Well, if you find the above code hard-understand, you could first try to write a two-column version of that explicitly maint Ains columns (the previous column and the current column) and then simplify the Two-column version into the One-column Version like the above code:-)
[Leetcode] Edit Distance