码迷,mamicode.com
首页 > 其他好文 > 详细

P1439 【模板】最长公共子序列

时间:2019-05-23 10:58:29      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:子序列   ble   while   etc   链接   string   情况   end   一个   

题目链接

P1439 【模板】最长公共子序列

思路

第一种 $O(N^2)$

用f[i][j]表示第一个排列取到i位和第2个排列取到j位的公共子序列长度

$$f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1])$$

最后一种情况需满足$a[i]==b[i]$

对于$50%$的数据,$n≤1000$,应该可以过

第二种 $O(n \cdot log(n) )$

把a重新标号$1$到$n$,把b中和a相同的元素跑一遍最长上升子序列就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
using namespace std;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int n;
int a[100005],lcs[100005];
signed main()
{
    cin>>n;
    for(int i=1;i<=n;++i)
    {
        int x;
        cin>>x;
        a[x]=i;//标记 
    }
    int len=0;
    lcs[0]=-999;
    for(int i=1;i<=n;++i)
    {
        int x;
        cin>>x;
        int now=a[x];
        if(now>lcs[len])
        {
            lcs[++len]=now;
        }
        else
        {
            int j=lower_bound(lcs+1,lcs+len+1,now)-lcs;
            lcs[j]=now; 
        }
    }
    cout<<len;
    return 0;
}

关于lower_bound请看这篇博客点这里

手打二分的代码:

来自liuzitong

#include<bits/stdc++.h>
//#include<windows.h>
using namespace std;
int a[100001],c[100001],s;
int main(int argc, char const *argv[])
{
    int n,xx;
    a[0] = -100000;
    cin>>n;
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d",&xx);
        a[xx] = i;
    }
    int t;
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d",&t);
        t = a[t];
        if (t > c[s])
        {
            c[++s] = t;
        }
        else{
            int l = 1,h = s,m;
            while(l <= h){
                m = (l + h) / 2;
                if(t > c[m]) l =m + 1;
                else h = m - 1;
            }
            c[l] = t;
        }
    }
    cout<<s<<endl;
    return 0;
    // for (int i = 2; i <= n; ++i)
    // {
    //  for (int j = 1; j < i; ++j)
    //  {
    //      if (b[i] > b[j] && c[i] < c[j] + 1)
    //      {
    //          c[i] = c[j] + 1;
    //      }
    //  }
    // }
    
}

P1439 【模板】最长公共子序列

标签:子序列   ble   while   etc   链接   string   情况   end   一个   

原文地址:https://www.cnblogs.com/pyyyyyy/p/10910493.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!