剛開始看這個問題的時候,第一反應是先求出lcs再求出lcs的lis,事實上這是有問題的,我們並不能保證這麼求出的lcis是最長的,比如下面這個例子
example設第乙個串為a,第二個串為ba:7 1 5 6 4 2 7
b:7 1 5 4 6 7 2
按照遞迴的取「最長公共子串行」,取出:
7 1 5 6 2
此序列的「最長上公升子串行」為:
1 5 6 (len=3)
但原序列的「最長公共上公升子串行」為:
1 5 6 7 (len=4)
首先確定dp狀態f[i, j],表示前a串前i個字元和b串前j個字元且以b[j]為結尾的lcis
狀態方程:
對於當處於(a[i], b[j]) 狀態時 ,由於dp狀態就決定了,b[j]是一定作為這個狀態下lics的結尾的,所以對於a[i],就有兩種情況,將其納入lcis或者不納入,首先先說不講a[i]納入lcis的情況
(1)若是 a[i] != b[j] ,顯然是一定不能講a[i]與b[j]進行配對的,那麼問題就縮小成了前a的前i - 1個字元與b的前j個字元且以b[j]結尾的lcis,即f[i - 1, j]也就是說 ,i之前的以b[j]結尾的序列自然沒有改變,仍然是長度仍然是f[i−1][j]; 若是a[i] == b[i] 如果不想要a[i]與b[j]進行配對,是不是也會得到上面的結果,故當
不講a[i]與b[j]配對(或無法配對)時,f[i, j] = f[i - 1, j]
(2)當a[i] == b[j]且它們進行配對時,就要在a串前i - 1個字元和b的前j - 1個字元中找到乙個最長的序列,設這個序列以t結尾且b[t] < b[j],是不是就等價於
f[i, j] = max(f[i - 1, t]) + 1 (t > 0 && t < j && b[t] < b[j])
這樣就把這個問題可以轉化為最優子結構的問題,且得到狀態轉移方程如下
f[i - 1, j] (a[i] != b[j])
f[i, j] =
max(f[i - 1, t]) + 1 (t > 0 && t < j && b[t] < b[j]) (a[i] == b[j])
講上述思路轉化為**
for (int i = 1; i <= n; i ++ )}}
上面**的時間複雜度為o(n 3),是很不理想的,可以對其進行等價轉化為o(n 2)的優化
觀察第三層迴圈,可以發現每次迴圈求得的maxv是滿足a[i] > b[k]的f[i - 1][k] + 1
的字首最大值。,而且是在a[i] == b[j]的時候成立,且可以發現,在每一次進行第二層迴圈時,a[i]是不變的,這也就可以推出,與a[i]進行配對的b[j]的值也是暫時不變的,那麼把b[j]等價轉化為a[i],並將maxv提至第一層迴圈內,在每一次比較a[i]和b[j]時,一起講maxv處理出來,這樣就可以將其優化為如下的o(n 2)的**
for (int i = 1; i <= n; i++)
}
這樣其實已經夠了,但是追求優化的話,還可以進行空間的優化,不難發現,每一次都止利用了上一層的結果,那麼可以採用滾動陣列的方法進行空間優化
for (int i = 1; i <= n; i++)
}
#include using namespace std;
const int maxn = 3e3 + 5;
int f[maxn], a[maxn], b[maxn];
int n, ans;
int main()
}cout << ans << endl;
return 0;
}
LCIS 最長公共上公升子串行
1004 tyvj1071 lcis最長公共上公升子串行 description 熊大媽的奶牛在小沐沐的薰陶下開始研究資訊題目。小沐沐先讓奶牛研究了最長上公升子串行,再讓他們研究了最長公共子串行,現在又讓他們要研究最長公共上公升子串行了。小沐沐說,對於兩個串a,b,如果它們都包含一段位置不一定連續的...
LCIS (最長公共上公升子串行)
ac通道 題目含義就是求最長公共上公升子串行 首先考慮,最長公共上公升子串行 最長上公升子串行 最長公共子串行,可以通過lis和lcs的思想去考慮本題目。定義狀態 dp i j 表示a陣列的前i個和b陣列的前j個且以b j 結尾的lcis長度考慮狀態轉移 轉移有兩種情況 a i b j 時候的轉移,...
最長公共上公升子串行(LCIS)
題解熊大媽的奶牛在小沐沐的薰陶下開始研究資訊題目。小沐沐先讓奶牛研究了最長上公升子串行,再讓他們研究了最長公共子串行,現在又讓他們研究最長公共上公升子串行了。小沐沐說,對於兩個數列a和b,如果它們都包含一段位置不一定連續的數,且數值是嚴格遞增的,那麼稱這一段數是兩個數列的公共上公升子串行,而所有的公...