思路:首先要對子序列有乙個認識,這裡的子串行不是直接擷取的,而是從原序列中取出若干字元,而字元間的相對次序不發生改變。這樣求得的結果會出現歧義,也可能得到幾個滿足條件的結果,暫時不考慮。
很容易想到求解此題需要遍歷、比較,關鍵是如何比較?採用「減而治之,分而治之」的思路。
見下圖,先考慮序列a和b的最後乙個字元是相等的情況,那麼最後兩個字元就可以湊出乙個公共字元(注意:可能a序列的最後乙個字元已經和b序列的前某個字元匹配了,那麼讓a序列的最後乙個字元和b序列的最後乙個字元匹配,對結果也是沒有影響的,得到的公共子串行是一樣的)。當a和b的最後乙個字元匹配了,那麼就可以把最後乙個字元拿掉,考慮剩下的字元匹配情況,問題的規模變小了。
下面再考慮a和b的最後乙個字元不相等的情況,見下圖,這時a序列和b序列的最後乙個字元總有乙個不能匹配成功,把沒有辦法匹配成功的字元刪掉,再考慮剩下的字元的匹配情況,問題的規律也變小了。
綜合上述思路,**如下,分解,遞迴:
這裡寫**片
這樣的求解過程,似然完成了任務,但是演算法複雜度呢????對它的分析見下圖:
這裡出現的問題,也是使用遞迴求解通常會出現的問題。遞迴演算法的複雜度往往都是指數級別的,就像一棵樹一樣,不斷的進行**,而**的節點,可能出現大量重複計算的情況,如果規避了重複計算,會大幅降低時間複雜度,但是遞迴仍然浪費了空間。合適的辦法是使用動態規劃的思想,把遞迴問題轉成乙個迭代求解的問題。結合上述思路,寫出**如下:
這裡寫**片
上面的迭代式演算法,需要記錄每個子問題的區域性解,從而導致空間複雜度激增。實際上,這既不現實,亦無必要。可以對演算法進一步改進,使得每個子問題只需常數空間,即可保證得到最終的公共最長子序列(而非僅僅是長度)
這裡寫**片
最長公共子串行 最長公共子串
1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...
最長公共子串行 最長公共子串
1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...
最長公共子串 最長公共子串行
子串要求連續 子串行不要求連續 之前的做法是dp求子序列 include include include using namespace std const int inf 0x3f3f3f3f const int mod 1000000007 string s1,s2 int dp 1010 10...