P1439 最长公共子序列(二分求最长公共子序列)

2024-01-02 19:24:54

题目:??https://www.luogu.com.cn/problem/P1439

思想:

首先,我们可以想到,最长公共子序列,就是两段所含数字完全一样,并且数字的顺序也是完全一样的序列。

而顺序,我们可以想到类似哈希的思想,考虑建立一个类似map的关系数组f[ai]=i,那么我们找到的序列只要是上升的,顺序就是一样的,然后考虑数字完全一样,由于我们已经有了一个f[ai]=i,所以我们把对应的bi改成f[bi],就可以确保数字相等了呀!

这时,就是在f[bi]的数组中求个最长上升子序列了,二分搞一搞就好了。STL大法好!

代码:

?

// Problem: C - 最长公共子序列
// Contest: Virtual Judge - CQJTU-DP题单1——线性DP
// URL: https://vjudge.net/contest/574209#problem/C
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N = 2e5+5;
const int inf = 0x3f3f3f3f;

int n;
int a[N],b[N];
int f[N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	cin>>n;
	map<int,int> mp;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		mp[a[i]]=i;
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
		//cout<<mp[b[i]]<<' ';
	}
	//cout<<"\n";
	//mp[b[i]]可以表示a数组中的每个数在b中的位置保证数字一样
	//然后找最长上升子序列保证顺序一样
	memset(f,127,sizeof(f));
	f[0]=0;
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(mp[b[i]]>f[cnt]){  //找到b数组的最长上升子序列
			f[++cnt]=mp[b[i]];
		}
		else{
			int l=0,r=cnt;
			while(l<r){
				int mid=(l+r)/2;
				if(f[mid]>mp[b[i]]){
					r=mid;
				}
				else l=mid+1;
			}
			f[l]=min(mp[b[i]],f[l]);
		}
		/*
		for(int i=1;i<=cnt;i++){
			cout<<mp[i]<<' ';
		}
		cout<<"\n";
		*/
	}
	cout<<cnt<<"\n";
	
	
	
	return 0;	

}

文章来源:https://blog.csdn.net/m0_73896521/article/details/135344358
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。