參考自
最長公共子串行,就是找出兩個序列中最長的相同序列(不必連續)
比如abtck和aeck的最長子序列就是ack。
查詢出最長公共子串行需要一些數學方法。
首先設想,對於兩個序列
x:x1,x2,x3....xm
y:y1,y2,y3...yn
假設 xm 和 yn 是相同的,那麼只需要找到 xm -1,和ym-1的最長公共子串行,再加上 yn 就行了。
如果 xm 和 yn 不同,那麼就要計算2次了
先把 xm 去掉,用 xm-1個序列和 yn 算最長公共子串行。再把 xm 去掉,用 yn-1個元素和 xm 算最長公共子串行。
兩種的結果再比較,取較大的那個序列。
因此,可以通過兩個for,來比較任意2個子序列之間的最長公共子串行。
如果用數學公式表達,可以表示為
可以用二維陣列c[i,j]表示截止到x[i]的字串與截止到的y[j] 的字串的最長公共子串行長度。為了便於程式設計,我們隊c[i,0]和c[0,j]上的元素都初始化為0
編寫**後,可以生成如下的乙個表。
先不用去看箭頭。
看x2和y1之間的數字,因為都是b,所以這個值就是斜上角的數字+1=1。說明ab和b之間最長公共子串行長度為1.
再看x2和y2,乙個b乙個d,不相等,那麼就因為c[2,1]比c[1,2]大,所以就還是為1.說明ab和bd之間的最長公共子串行還是為1.
依次類推。直至填滿整個**。
箭頭可以用另乙個二維陣列表示,表示這個長度是從哪來計算出來的,用於後期的回溯。
這個表完成後,要獲取最長公共子串行就只需要回溯此表。按照箭頭的順序就可以了。
回溯的演算法也是依據這樣的乙個事實,即
如果 xm = yn ,那麼 xm 就是最長子序列中的乙個值。而且是最後乙個值。
然後找到 xm -1, yn 或者 xm , yn -1這兩組各自的最長公共子串行,去長的那個+ xm 就ok了。
如上圖,先找到x7和y6,由於不相同,就找x6和y6之間的。為啥是x6和y6而不是x7,y5,那是因為x6y6和x7y5的最長公共子串行都是4,所以我們就只約定一種取值方式就可以了。如果取x7,y5,則會導致另一種不同的結果。待會可以從**中看到。
接下來看具體**和結果。**的backtrack1和backtrack2其實是等價的。
此處我們定義的是如果(c[i - 1, j] >= c[i, j - 1])就按照向上的路徑走。
如果我們改為c[i - 1, j] == c[i, j - 1],則可以看到結過就不同了,但是都是最長公共子串行。
此處用到的演算法為動態規劃,理解這個演算法,需要仔細的看著演算法和**,好好想想,就會明白其中的奧妙。
usingsystem;
using
system.collections.generic;
using
system.linq;
using
system.text;
namespace
console.writeline();
} console.writeline();
console.writeline();
for(
inti = 0; i
console.writeline();
} console.writeline(backtrack2(b, x, x.length, y.length));
} static
void
lcslength(
string
x, string
y, int
[,] c,
char
[,] b)
else
//如果當前元素不相等,分2種情況計算公共子串行的長度
else
} } }
} static
string
backtrack1(
int[,] c,
string
x, string
y, int
i, int
j)
static
string
backtrack2(
char
[,] b,
string
x, int
i, int
j)
} }
最長公共子串行 動態規劃
經常會遇到複雜問題不能簡單地分解成幾個子問題,而會分解出一系列的子問題。簡單地採用把大問題分解成子問題,並綜合子問題的解匯出大問題的解的方法,問題求解耗時會按問題規模呈冪級數增加。為了節約重複求相同子問題的時間,引入乙個陣列,不管它們是否對最終解有用,把所有子問題的解存於該陣列中,這就是動態規劃法所...
最長公共子串行 動態規劃
關於用動態規劃法求兩個序列的最長公共子串行問題的相關知識見 王曉東 計算機演算法設計與分析 第三章。注意,這裡所指的最長公共子串行是可以不相鄰的,與平常所說的最長公共子串 相鄰的 不一樣。直接上 lcs.h ifndef lcs h define lcs h class lcstring endif...
最長公共子串行(動態規劃)
定義 乙個數列 如果分別是兩個或多個已知數列的子串行,且是所有符合此條件序列中最長的,則 稱為已知序列的最長公共子串行。考慮最長公共子串行問題如何分解成子問題,設a a0,a1,am 1 b b0,b1,bm 1 並z z0,z1,zk 1 為它們的最長公共子串行。不難證明有以下性質 1 如果am ...