首先要知道什麼是子串行?它和子串的區別:
子串是指字串中連續的n個字元。
子串行是指字串中不一定連續但先後順序不變的n個字元。
公共子串行是指在兩個字串中都含有的子串行,例如:asgpdf aosfdp 這兩個字串都包含子串行asf(asd,asp)等,並且這三個是最長的公共子串行,所以lcs並不是唯一的,但lcs的長度肯定是一定的(廢話…)。
這是乙個動態規劃的題目。對於可用動態規劃求解的問題,一般有兩個特徵:①最優子結構;②重疊子問題
①最優子結構
設 x=(x1,x2,…xn) 和 y= 是兩個序列,將 x 和 y 的最長公共子串行記為lcs(x,y)
找出lcs(x,y)就是乙個最優化問題。因為,我們需要找到x 和 y中最長的那個公共子串行。而要找x 和 y的lcs,首先考慮x的最後乙個元素和y的最後乙個元素。
1)如果 xn=ym,即x的最後乙個元素與y的最後乙個元素相同,這說明該元素一定位於公共子串行中。因此,現在只需要找:lcs(xn-1,ym-1).
2)如果xn != ym,這下要麻煩一點,因為它產生了兩個子問題:lcs(xn-1,ym) 和 lcs(xn,ym-1)
因為序列x 和 序列y 的最後乙個元素不相等嘛,那說明最後乙個元素不可能是最長公共子串行中的元素。
lcs(xn-1,ym)表示:最長公共序列可以在(x1,x2,…x(n-1)) 和 (y1,y2,…yn)中找。
lcs(xn,ym-1)表示:最長公共序列可以在(x1,x2,…xn) 和 (y1,y2,…y(n-1))中找。
求解上面兩個子問題,得到的公共子串行誰最長,那誰就是 lcs(x,y)。用數學表示就是:
lcs=max
因此,我們成功地把原問題 轉化 成了 三個規模更小的子問題。
②重疊子問題
重疊子問題是啥?就是說原問題 轉化 成子問題後, 子問題中有相同的問題.。
原問題是:lcs(x,y)。子問題有 ❶lcs(xn-1,ym-1) ❷lcs(xn-1,ym) ❸lcs(xn,ym-1)
初一看,這三個子問題是不重疊的。可本質上它們是重疊的。舉例:
第二個子問題:lcs(xn-1,ym) 就包含了:問題❶lcs(xn-1,ym-1),為什麼?
因為,當xn-1 和 ym 的最後乙個元素不相同時,我們又需要將lcs(xn-1,ym)進行分解:分解成:lcs(xn-1,ym-1) 和 lcs(xn-2,ym)
也就是說:在子問題的繼續分解中,有些問題是重疊的。
由於像lcs這樣的問題,它具有重疊子問題的性質,因此:用遞迴來求解就太不划算了。因為採用遞迴,它重複地求解了子
問題啊。而且注意哦,所有子問題加起來的個數 可是指數級的哦。。。。
採用動態規劃時,並不需要去一 一 計算那些重疊了的子問題。或者說:用了動態規劃之後,有些子問題 是通過 「查表「 直接得到的,而不是重新又計算一遍得到的。
通過上面的分析我們也已經得到了動態規劃的轉移方程:
(dp[i][j]表示第乙個串的前i個和第二個串的前j個的lcs)。
**模板:
#include
#include
using
namespace std;
int n,m;
int a[
5010
],b[
5010];
int f[
5010][
5010];
int ans;
intmain()
} cout<
[m]<
return0;
}
LCS 最長公共子串行
問題描述 我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行當且僅當存在嚴格上 公升的序列 i1,i2,ik 使得對 j 1,2,k,有 xij zj。比如z a,b,f,c 是 x a,b,c,f,b,c 的子串行。現在給出兩個序列 x和 y,你的任務是找到 x和 y的最大公共子...
LCS最長公共子串行
求兩個字串的最大公共子串行問題 子串行的定義 若給定序列x 則另一串行z 是x的子串行是指存在乙個嚴格遞增下標序列使得對於所有j 1,2,k有 zj xij。例如,序列z 是序列x 的子序列,相應的遞增下標序列為。分析 用動態規劃做 1.最長公共子串行的結構 事實上,最長公共子串行問題具有最優子結構...
LCS最長公共子串行
lcs是longest common subsequence的縮寫,即最長公共子串行。乙個序列,如果是兩個或多個已知序列的子串行,且是所有子串行中最長的,則為最長公共子串行。複雜度對於一般的lcs問題,都屬於np問題。當數列的量為一定的時,都可以採用動態規劃去解決。解法動態規劃的乙個計算最長公共子串...