bzoj1264 基因匹配Match (lcs转lis lcs(nlogn))

基因匹配Match

内存限制:256 MiB 时间限制:1000 ms 标准输入输出

题目描述

基因匹配(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序列; ? 计算它们的最大匹配; ? 向输出文件打印你得到的结果。

输入格式

输入文件中第一行有一个整数N,表示这个星球上某种生物使用了N种不同的碱基,以后将它们编号为1…N的整数。 以下还有两行,每行描述一个DNA序列:包含5N个

1…N的整数,且每一个整数在对应的序列中正好出现5次。

输出格式

输出文件中只有一个整数,即两个DNA序列的最大匹配数目。

样例

样例输入

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

样例输出

7

数据范围与提示

60%的测试数据中:1<=N <= 1 000

100%的测试数据中:1<=N <= 20 000

lcs(nlogn)直接模板搞

具体操作lcs转lis

因为lis可以nlogn

所以lcs可以nlogn

别的博客写的什么树状数组

要是真到考试我绝对想不到这种做法

我太菜了

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define A 200001
 4 using namespace std;
 5 ll id=0,num=0,n,a[A],b[A],f[A],lis[A],o[A+A+A+A+A],len=0;
 6 vector <ll> fl[A];
 7 inline ll read()
 8 {
 9     ll f=1,x=0;
10     char ch=getchar();
11     while(ch<‘0‘||ch>‘9‘)
12     {
13         if(ch==‘-‘) f=-1;
14         ch=getchar();
15     }
16     while(ch>=‘0‘&&ch<=‘9‘)
17     {
18         x=(x<<1)+(x<<3)+(ch^48);
19         ch=getchar();
20     }
21     return f*x;
22 }
23 int main()
24 {
25     n=read();n*=5;
26         for(ll i=1;i<=n;i++)
27         {a[i]=read();b[n-i+1]=a[i];}
28     for(ll i=1;i<=n;i++)
29     {
30         b[i]=read();
31         fl[b[i]].push_back(i);
32     }
33     for(ll i=1;i<=n;i++)
34     {
35         ll nu=4;
36         while(nu>=0)
37         {
38             o[++num]=fl[a[i]][nu];
39             nu--;
40         }
41     }
42     for(ll i=1;i<=num;i++)
43     {
44         if(len==0||lis[len]<o[i])
45             lis[++len]=o[i];
46         else
47         {
48             ll p=lower_bound(lis,lis+len,o[i])-lis;
49             lis[p]=o[i];
50         }
51     }
52     cout<<len<<endl;
53 }

原文地址:https://www.cnblogs.com/znsbc-13/p/11072789.html

时间: 2024-10-19 17:34:31

bzoj1264 基因匹配Match (lcs转lis lcs(nlogn))的相关文章

BZOJ 1264 基因匹配Match(LCS转化LIS)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1264 题意:给出两个数列,每个数列的长度为5n,其中1-n每个数字各出现5次.求两个数列的最长公共子列. 思 路:首先找出每个数字在第二个数列中出现的位置,对于第一个数列构造出一个新的数列,每个数用这个数在第二个数列中出现的5个位置代替.这样求最长上升子 列.注意的是,在求到每个数(这里指原第一个数列中的每个数)为止的LIS时,替换后的5个数字要先求大的..不清楚的看代码. int a

BZOJ 1264: [AHOI2006]基因匹配Match( LCS )

序列最大长度2w * 5 = 10w, O(n²)的LCS会T.. LCS 只有当a[i] == b[j]时, 才能更新答案, 我们可以记录n个数在第一个序列中出现的5个位置, 然后从左往右扫第二个序列时将第一个序列对应位置的值更新, 用树状数组维护. 时间复杂度O(nlogn) ------------------------------------------------------------------------------------------------- #include<bi

BZOJ-1264 :[AHOI2006]基因匹配Match(树状数组+DP)

1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 904  Solved: 578[Submit][Status][Discuss] Description 基因匹配(match) 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的DNA序列由无数种碱基排列而成(地球上只有4种),而更奇怪的是,组成DNA序列的每一种碱基在该序列中正好出现5次!这样如果一个DNA序列有N种不同的碱基构成

BZOJ1264 [AHOI2006]基因匹配Match 动态规划 树状数组

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1264 题意概括 给出两个长度为5*n的序列,每个序列中,有1~n各5个. 求其最长公共子序列长度. 题解 我们发现这题的序列特殊性是关键! 我们只需要知道每一种数字在某一个序列中的5个位置,然后对于普通的LCS问题,我们只有在a[i] = b[j]的时候才会+1. 那么我们可以维护一个树状数组,在a序列中,我们一个一个位置扫过去,每次通过树状数组维护的前缀最大值来更新,然后因为修改不多,所以维护

[BZOJ1264][AHOI2006]基因匹配Match(DP + 树状数组)

传送门 有点类似LCS,可以把 a[i] 在 b 串中的位置用一个链式前向星串起来,由于链式前向星是从后往前遍历,所以可以直接搞. 状态转移方程 f[i] = max(f[j]) + 1 ( 1 <= j  < i && a[i] == b[j] ) ——代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 7

BZOJ1264: [AHOI2006]基因匹配Match

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1264 因为每个字符至多出现5次,在A中记录下来.然后在B中扫一遍,因为a[i]=b[j]时f[i]++,所以维护一个树状数组记录最大值就可以了. 注意转移的顺序 #include<cstring> #include<iostream> #include<cstdio> #include<map> #include<cmath> #includ

BZOJ 1264 [AHOI2006]基因匹配Match

有一定思维难度的题目..看了mps大爷的题解才会做(%%% mps) 考虑暴力O(n^2)dp的算法,只有当A[i] == B[j]时才会+1.我们可以利用这个性质,记录下每个数在A[i]中的5个位置.然后从前往后扫描B,顺便转移.转移时要维护前缀max,这个可以用树状数组随意维护一下.时间复杂度是O(nlogn)的 具体看代码 1 //F[i]表示B与A中前i个数的LCS长度 2 3 #include <cstdio> 4 #include <algorithm> 5 6 usi

BZOJ 1264 AHOI2006 基因匹配Match 动态规划+树状数组

题目大意:给定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)

【DP+树状数组】BZOJ1264-[AHOI2006]基因匹配Match

[题目大意] 给定n个数和两个长度为n*5的序列,两个序列中的数均有1..n组成,且1..n中每个数恰好出现5次,求两个序列的LCS. [思路] 预处理每个数字在a[i]中出现的五个位置.f[i]示以a[i]为末尾的最长公共子串(*这样就可以避免讨论交叉). 依次处理b[i],对于每个b[i]找到a[i]中的五个位置转移,用nowp表示,转移很简单:f[nowp]=max(f[nowp],query(nowp-1)+1),这里需要维护前缀最大值. 才知道前缀最大值可以用BIT来维护. 不过要注意