简要阐述
最长上升子序列:
给定n个整数A1…Aj,按照从左到右的顺序选出尽量多的整数,组成一个上升子序列。求最长子序列的长度。
1、首先定状态:fi 表示以Ai为结尾的最长上升序列
2、转化方程:初始化f1=1;
3、答案就是max( fi )
最长公共子序列:
给出两个序列A,B,求长度最大的公共子序列的长度
1、首先定状态: f[ i ][ j ]是A1,A2…Ai和B1,B2…Bj的最长公共子序列的长度;
2、转化方程
首先初始化:f[ 1][0]=f[0][1]=f[0][0]=0;
具体题目
分析
1、求最长上升子序列:时间复杂度为O(n^2)
for(int i=1;i<=n;i++){
int j=1,tmax=0;
while(j<i){
if(a[j]<a[i])
tmax=max(tmax,f[j]);
j++;
}
f[i]=tmax+1;
ans=max(ans,f[i]);
}
2、求最长公共子序列:时间复杂度为O(n*m)
for(int i=1;i<=n;i++){
for(int k=1;k<=m;k++){
if(a[i]==b[k]){
dp[i][k]=dp[i-1][k-1]+1;
}else{
dp[i][k]=max(dp[i-1][k],dp[i][k-1]);
}
}
}
代码
#include<stdio.h>
#include<algorithm>
using namespace std;
int n,m,a[5005],b[5005],f[5005],dp[5005][5005];
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
}
//求最长上升子序列的长度
int ans=0;
f[1]=1;
for(int i=1;i<=n;i++){
int j=1,tmax=0;
while(j<i){
if(a[j]<a[i])
tmax=max(tmax,f[j]);
j++;
}
f[i]=tmax+1;
ans=max(ans,f[i]);
}
printf("%d ",ans);
//求最长公共子序列的长度
dp[1][0]=0;dp[0][1]=0;dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int k=1;k<=m;k++){
if(a[i]==b[k]){
dp[i][k]=dp[i-1][k-1]+1;
}else{
dp[i][k]=max(dp[i-1][k],dp[i][k-1]);
}
}
}
printf("%d\n",dp[n][m]);
return 0;
}