問題描述:
給定兩個字串,求解這兩個字串的最長公共子串行。如:s1=,s2=,其最長公共子串行為,最長公共子串行長度為4。
最優子結構性質分析:
設序列s1=和s2=的最長公共子串行為s= ,則
1)若xn=ym ,那麼 zk=xn=ym 且 s[k-1]是s1[n-1] 和 s2[m-1]的最長公共子串行;
2)若xn≠ym 且 zk≠xn 則 s[k]是s1[n-1]和 s2[m]的最長公共子串行;
3)若xn≠ym 且 zk≠ym 則 s[k]是s1[n]和 s2[m-1] 的最長公共子串行。
由此可見,兩個序列的最長公共子串行包含了這兩個序列的字首的最長公共子串行。因此,最長公共子串行問題具有最優子結構性質,可以用動態規劃求解。
建立遞迴關係:
dp[i][j]表示:s1的前i個字元和s2的前j個字元的最長公共子串行長度。
自底向上求解最優值:
if(s1[i]==s2[j]) 「↖」 用1代表
if(dp[i-1][j]>dp[i][j-1]) 「↑」 用2代表
if(dp[i-1][j]<=dp[i][j-1]) 「←」 用3代表
時間複雜度:o(nm)。
根據計算最優值時得到的資訊,構造最優解:
時間複雜度:o(n+m)。
完整**
#include
using
namespace std;
#define n 100
int n,m;
char s1[n]
,s2[n]
;int dp[n]
[n];
int b[n]
[n];
void
lcslength()
for(
int i=
1;i<=n;i++
)for
(int j=
1;j<=m;j++
)else
if(dp[i-1]
[j]>dp[i]
[j-1])
else}}
void
lcs(
int i,
int j)
else
if(b[i]
[j]==2)
lcs(i-
1,j)
;else
lcs(i,j-1)
;}intmain()
cout<
for(
int i=
1;i<=n;i++)}
/*71 5 2 8 9 3 6
65 6 8 9 3 7
*/
具體講解
具體講解
最長公共子串行 動態規劃
經常會遇到複雜問題不能簡單地分解成幾個子問題,而會分解出一系列的子問題。簡單地採用把大問題分解成子問題,並綜合子問題的解匯出大問題的解的方法,問題求解耗時會按問題規模呈冪級數增加。為了節約重複求相同子問題的時間,引入乙個陣列,不管它們是否對最終解有用,把所有子問題的解存於該陣列中,這就是動態規劃法所...
最長公共子串行 動態規劃
關於用動態規劃法求兩個序列的最長公共子串行問題的相關知識見 王曉東 計算機演算法設計與分析 第三章。注意,這裡所指的最長公共子串行是可以不相鄰的,與平常所說的最長公共子串 相鄰的 不一樣。直接上 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 ...