1. 程式人生 > >[leetcode-583-Delete Operation for Two Strings]

[leetcode-583-Delete Operation for Two Strings]

code ngs alt splay ges exc ++ 分享 之前

Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 the same,
where in each step you can delete one character in either string.
Example 1:
Input: "sea", "eat"
Output: 2
Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".
Note:
The length of given words won‘t exceed 500.
Characters in given words can only be lower-case letters.

思路:

首先求最長公共子序列(LCS),然後,用兩個字符串的長度分別減去公共子序列的長度,然後再相加即為要刪除的長度。

最長公共子序列是經典的動態規劃問題。

最長公共子序列問題存在最優子結構:這個問題可以分解成更小,更簡單的“子問題”,這個子問題可以分成更多的子問題,因此整個問題就變得簡單了。最長公共子序列問題的子問題的解是可以重復使用的,也就是說,更高級別的子問題通常會重用低級子問題的解。擁有這個兩個屬性的問題可以使用動態規劃算法來解決,這樣子問題的解就可以被儲存起來,而不用重復計算。這個過程需要在一個表中儲存同一級別的子問題的解,因此這個解可以被更高級的子問題使用。

動態規劃的一個計算最長公共子序列的方法如下,以兩個序列{\displaystyle X}技術分享

{\displaystyle Y}技術分享為例子:

設有二維數組技術分享表示技術分享技術分享位和技術分享技術分享位之前的最長公共子序列的長度,則有:

技術分享
技術分享

其中,技術分享技術分享的第技術分享位與技術分享的第技術分享位完全相同時為“1”,否則為“0”。

此時,技術分享中最大的數便是技術分享技術分享的最長公共子序列的長度,依據該數組回溯,便可找出最長公共子序列。

 int minDistance2(string word1, string word2)
     {
         vector<vector<int>> dp(word1.size()+1,vector<int>(word2.size()+1,0));
         for (int i = 0; i <= word1.size();i++)
         {
             
for (int j = 0; j <= word2.size();j++) { if (i == 0 || j == 0) dp[i][j] = 0; else if (word1[i-1] == word2[j-1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } int lcs = dp[word1.size()][word2.size()]; return word1.size() - lcs + word2.size() - lcs; }

參考:

http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/

https://zh.wikipedia.org/wiki/%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97

https://discuss.leetcode.com/topic/89285/java-dp-solution-longest-common-subsequence

[leetcode-583-Delete Operation for Two Strings]