[BZOJ1264] [AHOI2006]基因匹配Match

题目描述

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的整数。 以下还有两行,每行描述一个DNAzh%的测试数据中:1<=N <= 20 000

题目分析

注意到题目里的性质 每个数出现不超过5次
那我们就将s1每个数的位置存下来 然后枚举s2每一个字符在s1的位置,找这个位置之前的最大DP值 相当于保证了结尾数字相同
用树状数组维护就好了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int n,v[100100],f[100100],ans;
vector<int> a[20100];
void update(int x,int c) { for(;x<=5*n;x+=x&-x) f[x]=max(f[x],c); }
int ask(int x) { int sum=0; for(;x;x-=x&-x) sum=max(sum,f[x]); return sum; }
int main()
{
    scanf("%d",&n);
    for(int x,i=1;i<=5*n;i++) scanf("%d",&x),a[x].push_back(i);
    for(int x,i=1;i<=5*n;i++)
    {
        scanf("%d",&x);
        for(int j=0;j<a[x].size();j++)
            v[a[x][j]]=max(v[a[x][j]],ask(a[x][j]-1)+1),ans=max(ans,v[a[x][j]]);
        for(int j=0;j<a[x].size();j++)
            update(a[x][j],v[a[x][j]]);
    }
    printf("%d",ans);
}


发表评论

电子邮件地址不会被公开。 必填项已用*标注