题意,最长公共上升子序列
dp数组记录以ai和bj结尾的两子串的最长公共上升子序列的长度
先讨论a[i]!=b[j]的情况,此时相当于从状态(a[i-1],b[j])增加了一个a[i]元素但a[i]!=b[j],所以应当继承状态(a[i-1],b[j]);那么为什么不去继承状态(a[i],b[j-1])呢,因为是从状态(a[i],0)= 0开始的,没能继承之前的状态。
现在讨论当a[i]=b[j]的情况。对于当前的a[i]和b[j](a[i]不一定等于b[j],状态(a[i],b[j])表示以a[i]和b[j]结尾的两子串的最长公共上升子序列的长度),尝试加入b[j+1],此时假定a[i]=b[j+1],那么必定要发生转移,从b串中找到一个b[x],当b[x]<b[j+1]=a[i]时,就可由状态(a[i-1],b[x])+1转移到(a[i],b[j+1])。
对于b[x],b[x]=a[y]<b[j+1]=a[i],y<i,x<j+1
#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<cmath>
#define ll long long
#define fastio {ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);}
using namespace std;
const int maxn = 1e5 + 10;
const int inf = 1e9;
int dp[505][505];
int main()
{
//fastio;
int t;
scanf("%d", &t);
while (t--)
{
memset(dp, 0, sizeof(dp));
int n, m;
scanf("%d", &n);
vector<int>a(n + 1);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
scanf("%d", &m);
vector<int>b(m + 1);
for (int i = 1; i <= m; i++)
scanf("%d", &b[i]);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
if (a[i] == b[j])
{
for (int k = 0; k < j; k++)
if (b[k] < a[i])
dp[i][j] = max(dp[i][j], dp[i - 1][k] + 1);
}
else
dp[i][j] = dp[i - 1][j];
}
int ans = 0;
for (int i = 1; i <= m; i++)
ans = max(ans, dp[n][i]);
printf("%d
", ans);
if (t)printf("
");
}
return 0;
}