基因匹配(bzoj 1264)

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 000ios

/*
  考慮LCS如何優化。
  由於在作LCS時,只有a[i]==b[j],纔會加一,並且這道題相同的只有五個,因此能夠提早把位置記下來,用一維數組轉移。
  即f[i]=max(f[j]+1) a[i]==b[j],用樹狀數組維護一下最大值。
*/
#include<cstdio>
#include<iostream>
#define N 100010
using namespace std;
int f[N],pos[N][6],mx[N],n;
int query(int x){
    int ans=0;
    for(;x>0;x-=(x&-x))ans=max(ans,f[x]);
    return ans;
}
void change(int x,int v){
    for(;x<=n*5;x+=(x&-x))f[x]=max(f[x],v);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n*5;i++){
        int x;scanf("%d",&x);
        pos[x][++pos[x][0]]=i;
    }
    int ans=0;
    for(int i=1;i<=n*5;i++){
        int x;scanf("%d",&x);
        for(int j=5;j>=1;j--){
            int k=pos[x][j];
            f[k]=max(f[k],query(k-1)+1);
            change(k,f[k]);
            ans=max(ans,f[k]);
        }
    }
    printf("%d",ans);
    return 0;
}
相關文章
相關標籤/搜索