基因匹配Match(最长公共子序列) NlongN
来源:互联网 发布:java rsa加密 编辑:程序博客网 时间:2024/06/01 21:55
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82285#problem/F
题意:两个串,求最长公共子序列,有n个数,每个数都出现5次。设为a串和b串
分析:首先n<=20000,5*n=10^5 如果用普通的方法(O(N^2)),肯定会超时,因此需要优化。普通状态转移方程若a[i]==b[i]:dp[i][j]=dp[i-1][j-1]+1;否则,dp[i][j]=max(dp[i-1][j],dp[i][j-1]);这样每次遍历浪费了大量的时间。
我们可以把a串作为模式串,b串作为查找串。由于这里每个数只有5次,我们可以先存下a串中的每个数在b串中的5个数的位置,用f[a[i]][j]表示,a[i]这个数在b串中的id为j. 所以每次从a串中加入一个数字后,只需要遍历(这5个数要从后向前遍历,否则从前往后的话,计算后一个数会算重)这个数字在b串中的5个位置就可以更新到下一个状态才+1(因为找的就是公共子序列,只有当两个字母相等才+1)。
这样我们可以开个c[20000*5+1]的辅助数组,c[j]表示,当前,b串中的第j位置的数,最大可以与a串公共子序列的长度。当遍历a串的时候,对应b的5个数从后往前更新c[j],c[j]=max(c[1]......c[i-1])+1。那么,我们可以用线段数或树状数组求c[j]之前的最大值。当a串遍历完后,找出c串的最大值就是ans。
#include <iostream>#include <stdio.h>#include <math.h>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <string>#include <string.h>#include <map>#include <set>using namespace std;#define inff 1000000000#define maxn 20010int a[maxn*5],b[5*maxn],f[5*maxn][6];struct node{ int l,r,m;}tree[5*maxn*4];void bulid(int id,int l,int r){ tree[id].l=l; tree[id].r=r; tree[id].m=0; if (l!=r) { int mid=(l+r)/2; bulid(id*2,l,mid); bulid(id*2+1,mid+1,r); }}void pushup(int id){ tree[id].m=max(tree[id*2].m,tree[id*2+1].m);}void update(int id,int pos,int val){ if(tree[id].l==tree[id].r) { tree[id].m=val; } else { int mid=(tree[id].l+tree[id].r)/2; if(pos<=mid) update(id*2,pos,val); else if(pos>mid) update(id*2+1,pos,val); pushup(id); }}int query(int id,int l,int r){ if(l<=tree[id].l&&tree[id].r<=r) { return tree[id].m; } else { int mid=(tree[id].l+tree[id].r)/2; if(r<=mid) return query(id*2,l,r); else if(l>mid) return query(id*2+1,l,r); else { int a=query(id*2,l,r); int b=query(id*2+1,l,r); return max(a,b); } }}int main(){ int i,n,j; while(scanf("%d",&n)!=EOF) { for(i=1;i<maxn;i++) { for(j=1;j<=5;j++) { f[i][j]=-1; } } for(i=1;i<=5*n;i++) { scanf("%d",&a[i]); } for(i=1;i<=5*n;i++) { scanf("%d",&b[i]); for(j=1;j<=5;j++) if(f[b[i]][j]==-1) { f[b[i]][j]=i;break;//存下这个数的出现的5个id } } bulid(1,1,n*5); int maxx; for(i=1;i<=5*n;i++)//遍历a { for(j=5;j>=1;j--)//从后向前遍历这个数的5个id { if(f[a[i]][j]==1)//如果id==1,它的最大值肯定为1 { update(1,f[a[i]][j],1);continue; } maxx=query(1,1,f[a[i]][j]-1); update(1,f[a[i]][j],maxx+1); } } printf("%d\n",query(1,1,n*5)); // printf("%d\n",tree[1].m); } return 0;}
0 0
- 基因匹配Match(最长公共子序列) NlongN
- UVA 10635 Prince and Princess 最长公共子序列(nlongn)
- uva 10100 Longest Match(最长公共子序列)
- UVA 10100- Longest Match(dp之最长公共子序列)
- 最长公共子串、最长公共子序列、最长回文子串、模式匹配、最大子序列--字符串问题整理
- 最长公共子串、最长公共子序列、最长回文子串、模式匹配、最大子序列--字符串问题整理
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列...
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 安卓发版 混淆、第三方平台加固加密、渠道分发 完整教程(图文)
- Linux C编程——常用头文件
- JVM优化总结
- Xcode .a静态库编译
- 【VB】MSHFlexGrid中数据导入到Excel(机房问题)
- 基因匹配Match(最长公共子序列) NlongN
- 计算二叉树叶子结点,加深理解遍历的本质
- 大规模集群自动化部署工具--Chef的安装部署
- libsvm中java.lang.NoSuchFieldException: rand
- 我所理解的activity与fragment(1)
- 什么是mimorGC什么是Full GC
- ACdream 1726A Math game
- 前端页面——揭开级联查询的面纱
- 3DMAX 7 角色建模1 人头建模