zoukankan      html  css  js  c++  java
  • bzoj 1264 基因匹配

    Written with StackEdit.

    Description

    卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的(DNA)序列由无数种碱基排列而成(地球上只有(4)种),而更奇怪的是,组成(DNA)序列的每一种碱基在该序列中正好出现(5)次!这样如果一个(DNA)序列有(N)种不同的碱基构成,那么它的长度一定是(5N)

    任务:编写一个程序:

    • 从输入文件中读入两个等长的(DNA)序列;
    • 计算它们的最长公共子序列长度;
    • 向输出文件打印你得到的结果。

    Input

    输入文件中第一行有一个整数(N),表示这个星球上某种生物使用了N种不同的碱基,以后将它们编号为(1…N)的整数。

    以下还有两行,每行描述一个(DNA)序列:包含(5N)(1…N)的整数,且每一个整数在对应的序列中正好出现(5)次。

    Output

    输出文件中只有一个整数,即两个(DNA)序列的最长公共子序列长度。

    Sample Input

    2
    1 1 2 2 1 1 2 1 2 2
    1 2 2 2 1 1 2 2 1 1

    Sample Output

    7

    HINT

    [数据约束和评分方法]

    (60\%)的测试数据中:(1<=N <= 1000.)
    (100\%)的测试数据中:(1<=N <= 20000.)

    Solution

    • 朴素的(O(n^2)dp)只能解决(60\%)的部分.
    • 注意到一个关键性质,每个数在每个序列中都恰好出现(5)次.
    • 类似于给两个排列求(LCS),我们可以记录下每个数字在第一个序列(a)中从前往后的(5)个位置.
    • 再处理第二个序列(b),此时我们处理当前数(b[i])在第一个序列中每个出现的位置(pos).有(a[pos]=b[i].)
    • 那么根据朴素(dp)的思路,定义(f[i])为只用(a)序列的前(i)个数的(LCS)长度.
    • 此时就可以完成更新(f[pos]=max(f[1)~(pos-1])+1).利用树状数组维护最大值进行优化.
    • 特别注意:每个(b[i])对应了(5)(pos),而我们处理它们的时候应该从后往前倒序处理,否则先更新的会对后面的造成影响,破坏无后效性(类似01背包).
    #include<bits/stdc++.h>
    #define lowbit(x) x&(-x)
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int MAXN=2e5+10;
    int ta[MAXN];
    int va[MAXN][10];
    int bit[MAXN];
    int n;
    inline void upd(int x,int c)
    {
    	for(;x<=n;x+=lowbit(x))
    		bit[x]=max(bit[x],c);
    }
    inline int query(int x)
    {
    	int res=0;
    	for(;x;x-=lowbit(x))
    		res=max(res,bit[x]);
    	return res;
    }
    int main()
    {
    	n=read();
    	n*=5;
    	for(int i=1;i<=n;++i)
    		{
    			int t=read();
    			va[t][++ta[t]]=i;
    		}
    	for(int i=1;i<=n;++i)
    		{
    			int t=read();
    			for(int j=5;j>=1;--j)//值得细细斟酌
    				{
    					int pos=va[t][j];
    					int mx=query(pos-1)+1;
    					upd(pos,mx);
    				}
    		}
    	int ans=query(n);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    冒泡排序
    Objective-C 命名规范
    时间轴的制作
    CocoaPods 哪些事
    消息转发机制入门篇
    架构
    算法学习
    AutoLayout自动布局
    网络学习
    HDU 3832 Earth Hour (最短路)
  • 原文地址:https://www.cnblogs.com/jklover/p/10070357.html
Copyright © 2011-2022 走看看