Descripción
La secuencia a 1, a 2, ..., a n se llama creciente, si a i < a i + 1 para i < n .
La secuencia s 1, s 2, ..., s k se llama subsecuencia de la secuencia a 1, a 2, ..., a n , si existe tal conjunto de índices 1 ≤ i 1 < i 2 < ... < i k ≤ n que a i j = s j . En otras palabras, la secuencia s se puede derivar de la secuencia a tachando algunos elementos.
Te dan dos secuencias de números enteros. Debe encontrar su subsecuencia creciente común más larga, es decir, una secuencia creciente de longitud máxima que es la subsecuencia de ambas secuencias.
Entrada
La primera línea contiene un número entero n (1 ≤ n ≤ 500), la longitud de la primera secuencia. La segunda línea contiene n enteros separados por espacios del rango [0, 10 ^ 9] - elementos de la primera secuencia. La tercera línea contiene un número entero m (1 ≤ m ≤ 500), la longitud de la segunda secuencia. La cuarta línea contiene m enteros separados por espacios del rango [0, 10 ^ 9] - elementos de la segunda secuencia.
Salida
En la salida de la primera línea k , la longitud de la subsecuencia creciente común más larga. En la segunda línea sale la subsecuencia misma. Separar los elementos con un espacio. Si hay varias soluciones, envíe cualquiera.
Ejemplos
entrada
7
2 3 1 6 5 4 6
4
1 3 5 6
salida
3
3 5 6
entrada
5
1 2 0 2 1
3
1 0 1
salida
2
0 1
La idea principal:
Dadas las matrices A y B cuya longitud es menor o igual a 500, encuentre su subsecuencia ascendente común más larga.
Análisis:
Expresado y estar compuesto de una longitud de la CLIS final.
Cuando el tiempo tiene
Cuando el tiempo tiene
Aquí, porque al enumerar k, se agota el tiempo de espera, así que optimícelo.
Record [0, todo j), el valor máximo utilizado para consulta directamente, a continuación, ponemos i como el bucle más externo, mantener constantemente este máximo, entonces se puede poner la complejidad el tiempo de inactividad .
Vea el código para una explicación específica.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 500 + 5;
int dp[maxn][maxn],p[maxn][maxn];
int a[maxn],b[maxn];
vector<int> v;
int n,m,ans,path;
void LCIS(int a[],int n,int b[],int m){
for(int i=1;i<=n;i++){//外层循环
int maxlen=0,pre=0;//maxlen代表dp[i-1][k]中的最大值,pre代表当前maxlen下的前一个B序列中选出的值(记录路径)
for(int j=1;j<=m;j++){
//这里假设Ai和Bj不等
dp[i][j]=dp[i-1][j];
p[i][j]=p[i-1][j];
if(a[i]==b[j]&&dp[i][j]<maxlen+1){//更新dp[i][j]和p[i][j]
dp[i][j]=maxlen+1;
p[i][j]=pre;
}
if(b[j]<a[i]&&dp[i-1][j]>maxlen){//更新maxlen和pre
maxlen=dp[i-1][j];
pre=j;
}
}
}
}
void Print(int pa) {//打印路径
if(!pa) return;
Print(p[n][pa]);
cout<<b[pa]<<" ";
}
int main() {
memset(dp,0,sizeof(dp));
memset(p,0,sizeof(p));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
}
LCIS(a,n,b,m);
//选出最长路径
for(int i=1;i<=m;i++){
if(ans<dp[n][i]){
ans=dp[n][i];
path=i;
}
}
printf("%d\n",ans);
Print(path);
return 0;
}