计蒜客习题:阿里天池的新任务


问题描述

阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串碱基序列 tt,判断它在另一个根据规则生成的 DNA 碱基序列 s 中出现了多少次。
定义序列 w:
这里写图片描述
输入格式
数据第一行为 5 个整数,分别代表 n , a , b , L , R。第二行为一个仅包含 A,T,G,C的一个序列代表 t。

数据保证 1<=n<=1e6, 0 < a < n,0≤b

神奇的炸裂代码


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=(1e6)+50;
int n,a,b,L,R;
char T[MAXN];
char P[MAXN];
int fail[MAXN];
int ans=0;

char whichalpha(int w){
    if(w>=L&&w<=R){
        if(w%2==0)return 'A';
        return 'T';
    }
    else{
        if(w%2==0)return 'G';
        return 'C';
    }
} 


void getFail() {
    int match = -1;
    fail[0] = -1;
    for (int i = 1; P[i]; ++i) {
        while (match >= 0 && P[match + 1] != P[i]) {
            match = fail[match];
        }
        if (P[match + 1] == P[i]) {
            match++;
        }
        fail[i] = match;
    }
    return;
}

void KMP() {  
    int  match = -1;   
    getFail();
    for (int i = 0; T[i]; ++i) {
        while (match >= 0 && P[match + 1] != T[i]) {
            match = fail[match];
        }
        if (P[match + 1] == T[i]) {
            match++;
            if (!P[match + 1]) {
                match=fail[match];
                ans++;
            }
        }
    }
    return;
}

int main()
{
    cin>>n>>a>>b>>L>>R;
    char tmp;
    int cnt=0;
    getchar();
    while (scanf("%c",&tmp)==1&&tmp!=10)P[cnt++]=tmp;
    T[0]=b;
    for(int i=1;i<n;i++){
        T[i]=(T[i-1]+a)%n;
    } 
    for(int i=0;i<n;i++){
        T[i]=whichalpha((int)T[i]);
    } 
    KMP();
    cout<<ans;
    return 0;
}

还没有出过这种问题,记一下,char为1bit而int为4bit,所以int可以表示2^32,而char是2^8=256哈哈哈哈第一次爆char。。。


AC代码


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=(1e6)+50;
int n,a,b,L,R;
char T[MAXN];
char P[MAXN];
int T1[MAXN];
int fail[MAXN];
int ans=0;

char whichalpha(int w){
    if(w>=L&&w<=R){
        if(w%2==0)return 'A';
        return 'T';
    }
    else{
        if(w%2==0)return 'G';
        return 'C';
    }
} 


void getFail() {
    int match = -1;
    fail[0] = -1;
    for (int i = 1; P[i]; ++i) {
        while (match >= 0 && P[match + 1] != P[i]) {
            match = fail[match];
        }
        if (P[match + 1] == P[i]) {
            match++;
        }
        fail[i] = match;
    }
    return;
}

void KMP() {  
    int  match = -1;   
    getFail();
    for (int i = 0; T[i]; ++i) {
        while (match >= 0 && P[match + 1] != T[i]) {
            match = fail[match];
        }
        if (P[match + 1] == T[i]) {
            match++;
            if (!P[match + 1]) {
                match=fail[match];
                ans++;
            }
        }
    }
    return;
}

int main()
{
    cin>>n>>a>>b>>L>>R;
    char tmp;
    int cnt=0;
    getchar();
    while (scanf("%c",&tmp)==1&&tmp!=10)P[cnt++]=tmp;
    T1[0]=b;
    for(int i=1;i<n;i++){
        T1[i]=(T1[i-1]+a)%n;
    } 
    for(int i=0;i<n;i++){
        T[i]=whichalpha(T1[i]);
    } 
    KMP();
    cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liukairui/article/details/80622518