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

题目链接

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请看这篇博客点这里

手打二分的代码:

#include<bits/stdc++.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;
}
posted @ 2019-05-23 10:34  pyyyyyy  阅读(207)  评论(6编辑  收藏  举报