zoukankan      html  css  js  c++  java
  • 洛谷 P1439 【模板】最长公共子序列(DP,LIS?)

    题目描述

    给出1-n的两个排列P1和P2,求它们的最长公共子序列。

    输入输出格式

    输入格式:

    第一行是一个数n,

    接下来两行,每行为n个数,为自然数1-n的一个排列。

    输出格式:

    一个数,即最长公共子序列的长度

    输入输出样例

    输入样例#1:

    5 
    3 2 1 4 5
    1 2 3 4 5
    

    输出样例#1:

    3
    

    说明

    【数据规模】

    对于50%的数据,n≤1000

    对于100%的数据,n≤100000

    Solve

    首先,来看一下N2N^2的算法:
    dp[i][j]={max(dp[i][j],dp[i1][j1]+1)a[i]==b[j]max(dp[i][j1],dp[i1][j])a[i]!=b[j] dp[i][j]=left{ egin{array}{rcl} max(dp[i][j],dp[i-1][j-1]+1) & & {a[i]==b[j]}\ max(dp[i][j-1],dp[i-1][j]) & & {a[i]!=b[j]} end{array} ight.
    dp[i][j]dp[i][j]代表aa数组的前ii位与bb数组的前jj位的最长公共子序列的长度

    dp[0][0]=(a[0]==b[0])dp[0][0]=(a[0]==b[0])

    用这个方法来写,对于10510^5的数据来说,时间和空间都是不够用的


    题中已经说明了:两个数组均是1-n的排列,即:两个数组的元素是相同的,只是元素所在的位置不同。那么,两个数组的公共子序列中的元素在两个数组中的相对位置是一样的

    如果按照下标给第一个数组的元素赋予新的值(按照升序),

    例如:a={3,1,2,4,5};b={1,3,2,4,5}a={3,1,2,4,5};b={1,3,2,4,5}

    old 3 1 2 4 5
    new 0 1 2 3 4

    aa进行处理后的数组为{0,1,2,3,4}{0,1,2,3,4}

    用在aa中创建的映射关系,将bb中的元素替换:

    old 1 3 2 4 5
    new 1 0 2 3 4

    得到的新的bb数组为:{1,0,2,3,4}{1,0,2,3,4}

    我们可以发现:新的bb数组的最长上升子序列即为原两个数组的最长公共子序列

    Code

    /*************************************************************************
    
    	 > Author: WZY
    	 > School: HPU
    	 > Created Time:   2019-02-08 15:20:18
    	 
    ************************************************************************/
    #include <bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define ms(a,b) memset(a,b,sizeof(a))
    #define INF 0x7f7f7f7f
    const int maxn=1e6+10;
    const int mod=1e9+7;
    using namespace std;
    int a[maxn];
    int b[maxn],b1[maxn];
    int vis[maxn];
    int dp[maxn];
    int main(int argc, char const *argv[])
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	int n;
    	cin>>n;
    	for(int i=0;i<n;i++)
    	{
    		cin>>a[i];
    		vis[a[i]]=i;
    	}
    	for(int i=0;i<n;i++)
    	{
    		cin>>b[i];
    		b1[i]=vis[b[i]];
    	}
    	int ans=0;
    	for(int i=0;i<n;i++)
    	{
    		int pos=lower_bound(dp,dp+ans,b1[i])-dp;
    		dp[pos]=b1[i];
    		ans=max(ans,pos+1);
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    VSCODE极简配置(备份)
    顺时针打印矩阵--剑指offer
    回文链表 leetcode
    E
    E. Kleof&#225;š and the n-thlon
    单调栈板子
    D
    CodeForces 600E Lomsat gelral(线段树合并)
    C# 面试宝典
    JavaScript 火花效果
  • 原文地址:https://www.cnblogs.com/Friends-A/p/11054973.html
Copyright © 2011-2022 走看看