1. 程式人生 > >【LCIS】最長公共上升子序列

【LCIS】最長公共上升子序列

1004 – 【TYVJ1071】LCIS最長公共上升子序列 Description   熊大媽的奶牛在小沐沐的薰陶下開始研究資訊題目。小沐沐先讓奶牛研究了最長上升子序列,再讓他們研究了最長公共子序列,現在又讓他們要研究最長公共上升子序列了。   小沐沐說,對於兩個串A,B,如果它們都包含一段位置不一定連續的數字,且數字是嚴格遞增的,那麼稱這一段數字是兩個串的公共上升子串,而所有的公共上升子串中最長的就是最長公共上升子串了。   奶牛半懂不懂,小沐沐要你來告訴奶牛什麼是最長公共上升子串。不過,只要告訴奶牛它的長度就可以了。 Input   第一行N,表示A,B的長度。   第二行,串A。   第三行,串B。 Output

  輸出長度。 Sample Input 4 2 2 1 3 2 1 2 3 Sample Output 2 *狀態轉移方程: ①F[i][j] = F[i-1][j] (a[i] != b[j]) ②F[i][j] = max(F[i-1][k]+1) (1 <= k <= j-1 && b[j] > b[k]) 現在我們來說為什麼會是這樣的狀態轉移方程呢? 對於①,因為F[i][j]是以b[j]為結尾的LCIS,如果F[i][j]>0那麼就說明a[1]…a[i]中必然有一個整數a[k]等於b[j],因為a[k]!=a[i],那麼a[i]對F[i][j]沒有貢獻,於是我們不考慮它照樣能得出F[i][j]的最優值。所以在a[i]!=b[j]的情況下必然有F[i][j]=F[i-1][j]。 對於②,前提是a[i] == b[j],我們需要去找一個最長的且能讓b[j]接在其末尾的LCIS。之前最長的LCIS在哪呢?首先我們要去找的F陣列的第一維必然是i-1。因為i已經拿去和b[j]配對去了,不能用了。並且也不能是i-2,因為i-1必然比i-2更優。第二維呢?那就需要列舉b[1]…b[j-1]了, 因為你不知道這裡面哪個最長且哪個小於b[j]。這裡還有一個問題,可不可能不配對呢?也就是在a[i]==b[j]的情況下,需不需要考慮F[i][j]=F[i-1][j]的決策呢?答案是不需要。因為如果b[j]不和a[i]配對,那就是和之前的a[1]…a[j-1]配對(假設F[i-1][j]>0,等於0不考慮), 這樣必然沒有和a[i]配對優越。為什麼必然呢? 因為b[j]和a[i]配對之後的轉移是max(F[i-1][k])+1,而和之前的i配對則是max(F[i
-1][k])+1。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=5005;
int a[maxn],b[maxn],f[maxn],n;
inline int read()
{
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
	return s*w;
}
int main()
{
	int i,j,maxx=0;
	n=read();
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	//a[i]=read();
	for(i=1;i<=n;i++)scanf("%d",&b[i]);
	//b[i]=read();
	for(i=1;i<=n;i++)
	{
		maxx=0;
		for(j=1;j<=n;j++)
		{
			if(b[j]<a[i]&&maxx<f[j])maxx=f[j];
			if(b[j]==a[i])f[j]=maxx+1;
		}
	}
	maxx=0;
	for(i=1;i<=n;i++)if(maxx<f[i])maxx=f[i];
	printf("%d",maxx);
	return 0;
}