码迷,mamicode.com
首页 > 其他好文 > 详细

计蒜之道 初赛第一场B 阿里天池的新任务(简单)

时间:2017-05-20 22:42:09      阅读:381      评论:0      收藏:0      [点我收藏+]

标签:next   ensure   line   模板匹配   成功   规则   imsi   pad   date   

阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串 DNA 碱基序列 tt,判断它在另一个根据规则生成的 DNA 碱基序列 ss 中出现了多少次。

首先,定义一个序列 ww:

 

\displaystyle w_{i} = \begin{cases}b, & i = 0\\(w_{i-1} + a) \mod n, & i > 0\end{cases}w?i??={?b,?(w?i1??+a)modn,???i=0?i>0??

 

接下来,定义长度为 nn 的 DNA 碱基序列 ss(下标从 00 开始):

 

\displaystyle s_{i} = \begin{cases}A , & (L \le w_{i} \le R) \land (w_{i}\ \mathrm{mod}\ 2 = 0)\\T , & (L \le w_{i} \le R) \land (w_{i}\ \mathrm{mod}\ 2 = 1)\\G , & ((w_{i} < L) \lor (w_{i} > R)) \land (w_{i}\ \mathrm{mod}\ 2 = 0)\\C , & ((w_{i} < L) \lor (w_{i} > R)) \land (w_{i}\ \mathrm{mod}\ 2 = 1)\end{cases}s?i??=?????????????????????A,?T,?G,?C,???(Lw?i??R)(w?i?? mod 2=0)?(Lw?i??R)(w?i?? mod 2=1)?((w?i??<L)(w?i??>R))(w?i?? mod 2=0)?((w?i??<L)(w?i??>R))(w?i?? mod 2=1)??

 

其中 \land∧ 表示“且”关系,\lor∨ 表示“或”关系,a\ \mathrm{mod}\ ba mod b 表示 aa 除以 bb 的余数。

现给定另一个 DNA 碱基序列 tt,以及生成 ss 的参数 n , a , b , L , Rn,a,b,L,R,求 tt 在 ss 中出现了多少次。

输入格式

数据第一行为 55 个整数,分别代表 n , a , b , L , Rn,a,b,L,R。第二行为一个仅包含ATGC的一个序列 tt。

数据保证 0 < a < n,0<a<n0 \le b < n,0b<n0 \le L \le R < n,0LR<n|t| \le 10^{6}t10?6??,a,na,n 互质。

对于简单版本,1 \leq n \leq 10^{6}1n10?6??;

对于中等版本,1 \leq n \leq 10^{9}, a = 11n10?9??,a=1;

对于困难版本,1 \leq n \leq 10^{9}1n10?9??。

输出格式

输出一个整数,为 tt 在 ss 中出现的次数。

样例说明

对于第一组样例,生成的 ss 为TTTCGGAAAGGCC

样例输入1

13 2 5 4 9
AGG

样例输出1

1

样例输入2

103 51 0 40 60
ACTG

样例输出2

5
构造序列,然后就是裸的KMP,第一场就出线,好幸运哈哈哈哈哈哈
/*
* @Author: lyucheng
* @Date:   2017-05-20 18:55:59
* @Last Modified by:   lyucheng
* @Last Modified time: 2017-05-20 20:43:25
*/

#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL res=0;
/*******************KMP模板***********************/
void makeNext(const char P[],LL Next[])
{
    /*
    Next[i]表示前i个字符中,最大前后缀相同的长度
    */
    LL q,k;
    LL m=strlen(P);
    Next[0]=0;
    for (q=1,k=0;q<m;++q)
    {
        while(k>0&&P[q]!=P[k])
            k = Next[k-1];
        /*
        这里的while循环很不好理解!
        就是用一个循环来求出前后缀最大公共长度;
        首先比较P[q]和P[K]是否相等如果相等的话说明已经K的数值就是已匹配到的长的;
        如果不相等的话,那么Next[k-1]与P[q]的长度,为什么呐?因为当前长度不合适
        了,不能增长模板链,就缩小看看Next[k-1]
        的长度能够不能和P[q]匹配,这么一直递归下去直到找到
        */
        if(P[q]==P[k])//如果当前位置也能匹配上,那么长度可以+1
        {
            k++;
        }
        Next[q]=k;
    }
}

void kmp(const char T[],const char P[],LL Next[])
{
    LL n,m;
    LL i,q;
    n = strlen(T);
    m = strlen(P);
    makeNext(P,Next);
    for (i=0,q=0;i<n;++i)
    {
        while(q>0&&P[q]!= T[i])
            q = Next[q-1];
        /*
        这里的循环就是位移之后P的前几个字符能个T模板匹配
        */
        if(P[q]==T[i])
        {
            q++;
        }
        if(q==m)//如果能匹配的长度刚好是T的长度那么就是找到了一个能匹配成功的位置
        {
            res++;
        }
    }
}
/*******************KMP模板***********************/
LL n,a,b,L,R;
char t[1000005];//用来匹配的子串
char p[100000005];
LL Next[100000005];
LL last,now;
LL len=0;
int main(){
    // freopen("in.txt","r",stdin);
    scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&L,&R);
    scanf("%s",t);
    for(int i=0;i<n;i++){
        if(i==0){
            now=b;
            if(now>=L&&now<=R){
                if(now%2==0){
                    p[len++]=A;
                }else{
                    p[len++]=T;
                }
            }else{
                if(now%2==0){
                    p[len++]=G;
                }else{
                    p[len++]=C;
                }
            }
        }else{
            now=(last+a)%n;
            if(now>=L&&now<=R){
                if(now%2==0){
                    p[len++]=A;
                }else{
                    p[len++]=T;
                }
            }else{
                if(now%2==0){
                    p[len++]=G;
                }else{
                    p[len++]=C;
                }
            }
        }
        last=now;
    }
    makeNext(t,Next);
    kmp(p,t,Next);
    printf("%lld\n",res);
    return 0;
}

 

计蒜之道 初赛第一场B 阿里天池的新任务(简单)

标签:next   ensure   line   模板匹配   成功   规则   imsi   pad   date   

原文地址:http://www.cnblogs.com/wuwangchuxin0924/p/6883353.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!