题目描述
给出两个序列A、B,求A的LIS和AB的LCS的长度(LIS严格递增)
Input
第一行两个数n,m(1<=n<=5,000,1<=m<=5,000)
第二行n个数,表示序列A
第三行m个数,表示序列B
Output
输出一行数据ans1和ans2,分别代表序列A的LIS和序列AB的LCS的长度
解题思路
主要是LIS和LCS的求解方法:
LIS:线性dp,定义fi为以ai结尾的LIS的长度,f1=1,转移方程为:fi=max(fj)+1,其中0<j<i且aj<ai,最终结果:max(fi)(i=1,2……n);
LCS:定义f(i,j)为a1到ai和b1到bj的LCS长度,f(1,0)=f(0,1)=f(0,0)=0,转移方程为:ai==bj时,f(i,j)=f(i-1,j-1)+1,否则,f(i,j)=max(f(i-1,j),f(i,j-1)),最终结果:f(n,m)。
实现代码
#include<iostream>
#include<algorithm>
using namespace std;
int a[5010],b[5010];
int f1[5010],f2[5010][5010];
void LIS(int n)
{
for(int i=2;i<=n;++i)
{
for(int j=1;j<i;++j)
{
if(a[j]<a[i])
f1[i]=max(f1[i],f1[j]+1);
}
}
}
void LCS(int n,int m)
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
if(a[i]==b[j])
f2[i][j]=f2[i-1][j-1]+1;
else
f2[i][j]=max(f2[i-1][j],f2[i][j-1]);
}
}
}
int main()
{
int n,m,ans_lis=0;
cin>>n>>m;
for(int i=1;i<=n;++i)
cin>>a[i];
for(int i=1;i<=m;++i)
cin>>b[i];
for(int i=1;i<=n;++i)
f1[i]=1;
LIS(n);
for(int i=1;i<=n;++i)
ans_lis=ans_lis<f1[i]?f1[i]:ans_lis;
f2[0][0]=0;
f2[0][1]=0;
f2[1][0]=0;
LCS(n,m);
cout<<ans_lis<<" "<<f2[n][m]<<endl;
return 0;
}
总结
这道题主要是对课上所讲的内容的一个练习,基本方法都已给出,照着写基本上没问题,这两种实现方法复杂度都是n^2,算是较为朴素且简单的方法。