這個問題是動態規劃演算法中的乙個經典問題,先看問題描述:
lcs:兩個字串 x和 y,找到他們最長的公共子串行,該序列不要求是連續的。公共子串行的意思就是序列的相對順序是不變的,但是序列不一定是連續的。
例如:x = "bdcaba"
y = "abcbdab"
他們的最長公共子串行是bcba和bdab,長度都為4,找到任意乙個即可。
lcs問題也滿足最優子結構:
定義 xi 表示x的前i個字元組成的序列,同理得到yj是y的前j個字元組成的序列。
定義 z(i,j)表示xi和yj的最長公共子串行的長度lcs(xi,yj)
如此,可知:
我們要計算lcs(xm,yn),則有如下情況:
1.x[m] = y[n],那麼z(m,n) = lcs(xm,yn) = lcs(xm-1,yn-1) + 1
2.當x[m] != y[n] ,那麼z(m,n) 便是 lcs(xm,yn-1)和lcs(xm-1,yn)中較大者。
lcs也滿足重疊子問題結構,計算lcs(xm,yn-1)和lcs(xm-1,yn)的時候也計算了lcs(xm-1,yn-1)。
因此,採用動態規劃演算法...
**如下:
// 最長公共子串行 lcs
// deng chao
// 2012.12.4
#include #include using namespace std;
// 計算lcs長度並記錄lcs各個字元的前驅
// z:儲存前驅記錄,用於得到公共子串行
// return: lcs長度
int lcs(const char *x , int xl, const char *y , int yl , char **&z)
// 初始化,很重要!
for(int i = 0 ; i <=xl; ++i)
for(int i = 0 ; i <= yl ; ++i)
// 從1開始填充表
for(int i = 1 ; i <= xl ; ++i)
else
else
}cout<<"c["《後記:
這裡描述的是找到乙個最長公共子串行,而在例子中也看到可能不止乙個序列,因此,如果要找到所有的最長公共子串行,應該怎麼處理???
思路:不採用記錄字首的矩陣z,而直接採用記錄長度的矩陣c
如果c[i][j] = c[i-1][j-1] + 1,則對應的值是最長公共序列的,且可以通過c[i-1][j-1]遞迴回溯;
如果c[i][j] = c[i-1][j] , 則該值不屬於最長公共序列,但也可以通過c[i-1][j]進行回溯,c[i][j] = c[i-[j-1]的情況相同
如此可以回溯所有的可能路徑,得到所有的最長公共序列。
動態規劃之最長公共子串行(lcs)
最長公共子串行的定義是,乙個數列z分別是已知數列的子串行 子串行不一定是連續序列,是在該序列中刪去若干元素後得到的序列 且是所有符合此條件序列中最長的,則z成為最長公共子串行lcs longest common subsequences 有些地方則說公共子串就是要求連續的子串行,有些地方則不是,這裡...
動態規劃之最長公共子串行(LCS)
動態規劃之最長公共子串行問題 前言 乙個給定序列的子串行,就是將給定的序列中零個或多個元素去掉後得到的結果。其形式化定義如下 給定乙個序列x 另乙個序列z 滿足如下條件時稱為x的子串行,即存在乙個嚴格遞增的x下表序列 i1,i2 ik 對所有j 1,2,3,k滿足xi zj例如z 是x 的子串行對應...
動態規劃之最長公共子串行(LCS)
動態規劃法 dynamic programming 通常用於求解最優化問題 optimization problem 它適用於最優子結構和重疊子問題。這顯然與分治法是不同的,分治法將問題劃分為不重疊的子問題,然後分別求解這些子問題,最後將這些問題合併得到最終的解。對於具有公共子問題的情況,分治法會做...