LCS(最长公共子序列)
P1439 【模板】最长公共子序列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
A:3 2 1 4 5
B:1 2 3 4 5
思路:
主要考虑离散化,先不离散化成数字,不好理解
A:3 2 1 4 5 → A:a b c d e
离散化之后A是单调递增的
举几个B的例子:× b × d × b,d是单调递增的,b,d是A,B的公共子序列之一
a × c d × a,c,d是单调递增的,a,c,d是A,B的公共子序列之一,
题目样例来说
A: a b c d e
B: c b a d e a,d /a,d,e都是递增的,都是A,B的公共子序列之一
B: c b a d e a,d /a,d,e都是递增的,都是A,B的公共子序列之一
显然这时候我们只用求离散化后,B的最长上升子序列,就是LCS的答案了
Code:
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back //vector函数 #define popb pop_back //vector函数 #define fi first #define se second const int N=1e5+10; //const int M=; //const int inf=0x3f3f3f3f; //一般为int赋最大值,不用于memset中 //const ll INF=0x3ffffffffffff; //一般为ll赋最大值,不用于memset中 int T,n,a[N],b[N],c[N],pos[N],f[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { // freopen("","r",stdin); // freopen("","w",stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(),pos[a[i]]=i; for(int i=1;i<=n;i++) b[i]=read(),c[i]=pos[b[i]]; 将b数组离散化成c数组 int ans=0; for(int i=1;i<=n;i++) { int l=1,r=ans; if(!ans) { ans=1,f[1]=c[1];continue; } while(l+1<r) { int mid=(l+r)/2; if(f[mid]<c[i]) l=mid; else r=mid; } int len; if(f[r]<c[i]) len=r; else if(f[l]<c[i]) len=l; else len=0; if(!f[len+1]) f[len+1]=c[i]; else f[len+1]=min(f[len+1],c[i]); ans=max(ans,len+1); } printf("%d\n",ans); return 0; }