题意:对于给定的长度为n的序列,找出第二长的最长长度
解题思路:与之前的求最长子序列有些不同。但是如果最长自序咧为ans,那么次长度只有ans-1,和ans两种情况。
由于n的范围比较小[0,1000],所以可以用求最长子序列的N^2的算法来将找最长子串的中间信息存储下来,跟求最长子序列一样开一个数组将以当前数为结尾的子序列的最大长度。再另开一个数组记录以当前数为结尾的最长子序列的取法个数。
最后就可以遍历最长子序列的取法有多少种,如果大于1则答案为ans,否则为ans-1。
AC代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1050;
int a[maxn];///存储原始数据
int c[maxn];///存储能到达i位置的最大长度的不同取法
int dp[maxn];///存储以a[i]结尾的最大上升子序列的长度
int main()
{
int n,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)///存储数据
scanf("%d",&a[i]);
int ans=0;
for(int i=0;i<n;i++)///n^2求最长子序列
{
dp[i]=1; c[i]=1;
for(int j=0;j<i;j++)
{
if(a[j]>=a[i]) continue;
if(dp[j]+1>dp[i])
{
dp[i]=dp[j]+1;
c[i]=c[j];///存储取法
}
else if(dp[j]+1==dp[i])
c[i]+=dp[j];///记录以当前数为结尾的最长序列的取法
}
if(ans<dp[i]) ans=dp[i];///ans记录最长子序列
}
int sum=0;
for(int i=0;i<n;i++)
{
if(dp[i]==ans) sum+=c[i];///最长子序列的取法
}
if(sum>1)
printf("%d\n",ans);
else
printf("%d\n",ans-1);
}
return 0;
}