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;
}