題目:common subsequence
題目描述:給定兩個字串a和b(或數字序列),求乙個字串,使得這個字串是所給兩個字串的最長公共部分(可以不連續)
動態規劃的做法:時間複雜度,o(n*m)
**:
#include
#include
#include
#include
using namespace std;
const
int manx=
2e3+10;
const
int inf=
1e9;
int dp[manx]
[manx]
;int
main()
printf
("%d\n"
,dp[i-1]
[j-1])
;}}
例題:greatest common increasing subsequence
題目描述:在最長公共子串行的基礎上,增加乙個上公升子串行的條件
假設和最長公共子串行一樣,我們規定dp[i][j]表示a的i號位和b的j號位前的lcis。在最長公共子串行中,當a[i]=b[j]時,我們直接用dp[i-1][j-1]+1來更新dp[i][j]。但在這裡,因為有上公升的限制,就不能直接通過dp[i-1][j-1]+1來得到dp[i][j]了,因為a的i-1號位和b的j-1號位前的lcis中的最後一位數不一定<
<
<
a[i]。
所以為了判斷能否通過前面的dp值來更新dp[i][j],我們這樣規定:設dp[i][j]表示a的i號位和b的j號位前並且以b[j]為結尾的lcis的長度。
這樣當a[i]=b[j]時,我們就可以尋找最大的dp[i-1][k]來更新dp[i][j](1≤
\leq
≤k≤\leq
≤j-1,b[k]<
<
<
b[j])
最後就剩下了怎麼確定k值的問題,很容易想到我們可以列舉1~j-1中所有符合條件(b[k]<
<
<
b[j])的dp[i-1][k]值,但這樣複雜度就到了o(n^3)。所以這裡我們換乙個思路:在第二層迴圈中,我們每次從左至右都更新了dp[i][1]到dp[i][m]所有值(m是序列b的長度),即以序列a固定的前i位去匹配序列b,所以這裡a[i]值是固定的,我們就可以維護乙個pos值,使得dp[i-1][pos]是在條件b[pos]**實現:
ans=0;
memset
(dp,0,
sizeof
(dp));
for(
int i=
1; i<=n; i++
)else dp[i]
[j]=dp[i-1]
[j];
}}
看到這裡不難發現每次更新只用到了dp[i-1]的那一層,所以dp我們可以優化成一維。
ans=0;
memset
(dp,0,
sizeof
(dp));
for(
int i=
1; i<=n; i++)}
}
變型例題:吉哥系列故事——完美隊形i
最長公共上公升子串行
題目描述 給定兩個整數序列,求它們的最長上公升公共子串行。輸入描述 輸入兩組資料,每組資料代表乙個整數序列,其輸入格式為 第一行輸入長度m 1 m 500 第二行輸入該序列的m個整數ai 231 ai 231 輸出描述 輸出共兩行。第一行輸出兩個序列的最長上公升公共子串行的長度l 第二行輸出該子串行...
最長公共上公升子串行
首先,在 a i b j 的時候有 dp i j dp i 1 j 為什麼呢?因為 dp i j 是以b j 為結尾的 lcia 如果dp i j 0 那麼就說明 a 1 a i 中必然有乙個字元 a k 等於b j 如果dp i j 等於0 呢?那賦值與否都沒有什麼影響了 因為 a k a i 那...
最長公共上公升子串行
熊大媽的奶牛在小沐沐的薰陶下開始研究資訊題目。小沐沐先讓奶牛研究了最長上公升子串行,再讓他們研究了最長公共子串行,現在又讓他們研究最長公共上公升子串行了。小沐沐說,對於兩個數列a和b,如果它們都包含一段位置不一定連續的數,且數值是嚴格遞增的,那麼稱這一段數是兩個數列的公共上公升子串行,而所有的公共上...