最長公共子序列-動態規劃DP

因爲比較有用,所以就轉來了,原文地址http://www.nocow.cn/index.php/%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97

概述

最長公共子序列:字符序列的子序列是指從給定字符序列中隨意地(不一定連續)去掉若干個字符(可能一個也不去掉)後所形成的字符序列。 令給定的字符序列X="x0,x1,...,xm -1",序列Y="y0,y1,...,yk-1"是X的子序列, 存在X的一個嚴格遞增下標序列,使得對所有的j=0,1,...,k-1,有xij= yj。例如,X="ABCBDAB",Y="BCDB"是X的一個子序列。 給定兩個序列A和B,稱序列Z是A和B的公共子序列,是指Z同是A和B的子序列。 問題要求已知兩序列A和B的最長公共子序列。

分析

本題初看有些類似線形動態規劃,但經過仔細審題發現用矩陣類動態規劃更好理解, 如下圖所顯示,我們把兩個字符串看作矩陣的橫縱軸: 首先讀入數據時,把兩個字符相同的標記成1,不相同的地方標記成0;

Image:B524cd08ff6111cb63d98674.jpg

很容易證明,如果能形成公共子序列,則最長子序列一定是從某個位置開始的對角線的長度,所以我們需要做的就是統計對角線的長度,DP方程就爲if a[i,j]=1 then d[i,j]:=d[i-1,j-1]+1;

經過循環我們就可以把上表轉化成: Image:2c4c7f7e02167e220dd7da71.jpg

因此我們只需記錄在循環中的最大值就是我們要的最長公共子序列的長度;

代碼:

優化:但是在0和1的矩陣中找最長的1對角線序列又要花去一定的時間。通過改進矩陣的生成方式和設置標記變量,可以省去這部分時間。

當字符匹配的時候,我們並不是簡單的給相應元素賦上1,而是賦上其左上角元素的值加一。

我們用兩個標記變量來標記矩陣中值最大的元素的位置,在矩陣生成的過程中來判斷當前生成的元素的值是不是最大的,據此來改變標記變量的值,那麼到矩陣完成的時候,

最長匹配子串的位置和長度就已經出來了.這樣做速度比較快,但是花的空間太多。我們注意到在改進的矩陣生成方式當中,每生成當前一層,前面的那一層就已經沒有用了。

因此我們只需使用一維數組即可。可以自己寫一下。

變種之一:字串距離

 

順便附上HDOJ Common Subsequence AC代碼一份

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章