最长公共子序列

Posted wang者归来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长公共子序列相关的知识,希望对你有一定的参考价值。

题目背景

DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列。

题目描述

经过长时间的摸索和练习,DJL终于学会了怎么求LCS。Johann感觉DJL孺子可教,就给他布置了一个课后作业:

给定两个长度分别为n和m的序列,序列中的每个元素都是正整数。保证每个序列中的各个元素互不相同。求这两个序列的最长公共子序列的长度。

DJL最讨厌重复劳动,所以不想做那些做过的题。于是他找你来帮他做作业。

输入输出格式

输入格式:

 

第一行两个整数n和m,表示两个数列的长度。

第二行一行n个整数a_1,a_2,…,a_n,保证1≤a_i≤〖10〗^9。

第三行一行m个整数b_1,b_2,…,b_m,保证1≤b_i≤〖10〗^9。

 

输出格式:

 

一行一个整数,表示两个数列的最长公共子序列的长度。

 

输入输出样例

输入样例#1:
6 6
1 3 5 7 9 8
3 4 5 6 7 8
输出样例#1:
4

说明

对于40%的数据,n, m≤3000

对于100%的数据,n, m≤300000

 

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;
map<int,int>f;
int  a[300009];
int n,m;
int c[400009],d[260000],aa,bb;
int lcs()
{
    int w,i,j;
    for(i=1;i<=n;i++)
        c[i]=f[a[i]];
    int s=1;
    while(c[s]==0)    c[s]=999999,s++;
    d[1]=c[1];    
    int t=1;    
    for(i=2;i<=n;i++)
    {
        int l=1,r=t,mid;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(d[mid]<c[i])
                l=mid+1;
            else r=mid-1;
        }
        d[l]=c[i];//可悲的弄错了变量
        if(l>t)
            t++;
    }
    return t;
}
int main()
{        
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int q;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&q);
        f[q]=i;
    }
    int ans=lcs();
    cout<<ans; 
    return 0;
}

 

以上是关于最长公共子序列的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列与最长公共字串

最长公共子序列

最长公共子序列

字符串最长公共子序列问题

最长公共子序列

最长公共子序列