zoukankan      html  css  js  c++  java
  • bzoj1264 [AHOI2006]基因匹配Match 树状数组+lcs

    1264: [AHOI2006]基因匹配Match

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1255  Solved: 835
    [Submit][Status][Discuss]

    Description

    基因匹配(match) 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的DNA序列由无数种碱基排列而成(地球上只有4种),而更奇怪的是,组成DNA序列的每一种碱基在该序列中正好出现5次!这样如果一个DNA序列有N种不同的碱基构成,那么它的长度一定是5N。 卡卡醒来后向可可叙述了这个奇怪的梦,而可可这些日子正在研究生物信息学中的基因匹配问题,于是他决定为这个奇怪星球上的生物写一个简单的DNA匹配程序。 为了描述基因匹配的原理,我们需要先定义子序列的概念:若从一个DNA序列(字符串)s中任意抽取一些碱基(字符),将它们仍按在s中的顺序排列成一个新串u,则称u是s的一个子序列。对于两个DNA序列s1和s2,如果存在一个序列u同时成为s1和s2的子序列,则称u是s1和s2的公共子序列。 卡卡已知两个DNA序列s1和s2,求s1和s2的最大匹配就是指s1和s2最长公共子序列的长度。 [任务] 编写一个程序:  从输入文件中读入两个等长的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 <= 1 000
    100%的测试数据中:1<=N <= 20 000

    Source

    给定n个数和两个长度为n*5的序列,每个数恰好出现5次,求两个序列的LCS

    n<=20000,序列长度就是10W,朴素的O(n^2)一定会超时

    所以我们考虑LCS的一些性质

    LCS的决策+1的条件是a[i]==b[j] 于是我们记录a序列中每个数的5个位置

    扫一下b[i] 对于每个b[i]找到b[i]在a中的5个位置 这5个位置的每个f[pos]值都可以被b[i]更新 于是找到f[1]到f[pos-1]的最大值+1 更新f[pos]即可

    这个用树状数组维护 时间复杂度O(nlogn)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cstdio>
     6 
     7 #define M 200007
     8 using namespace std;
     9 inline int read()
    10 {
    11     int x=0,f=1;char ch=getchar();
    12     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
    13     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    14     return x*f;
    15 }
    16 
    17 int n,ans;
    18 int a[M*5],b[M*5],c[M*5],f[M*5],pos[M][6];
    19 
    20 void Update(int x,int y)
    21 {
    22     for(;x<=n*5;x+=x&-x)
    23         c[x]=max(c[x],y);
    24 }
    25 int Get_Ans(int x)
    26 {
    27     int re=0;
    28     for(;x;x-=x&-x)
    29         re=max(re,c[x]);
    30     return re;
    31 }
    32 int main()
    33 {
    34     n=read();
    35     for(int i=1;i<=n*5;i++)
    36     {
    37         a[i]=read();
    38         pos[a[i]][++pos[a[i]][0]]=i;
    39     }
    40     for(int i=1;i<=n*5;i++)b[i]=read();
    41     for(int i=1;i<=n*5;i++)
    42         for(int j=5;j;j--)
    43         {
    44             int k=pos[b[i]][j];
    45             f[k]=max(f[k],Get_Ans(k-1)+1);
    46             Update(k,f[k]);
    47             ans=max(ans,f[k]);
    48         }
    49     printf("%d
    ",ans);
    50 }
  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8487803.html
Copyright © 2011-2022 走看看