阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串 DNA 碱基序列 tt,判断它在另一个根据规则生成的 DNA 碱基序列 ss中出现了多少次。
首先,定义一个序列 ww:
\displaystyle w_{i} =
{b,(wi−1+a)modn,i=0i>0{b,i=0(wi−1+a)modn,i>0
wi={b,(wi−1+a)modn,i=0i>0
接下来,定义长度为 nn 的 DNA 碱基序列 ss(下标从 00 开始):
\displaystyle s_{i} =
⎧⎩⎨⎪⎪⎪⎪⎪⎪A,T,G,C,(L≤wi≤R)∧(wi mod 2=0)(L≤wi≤R)∧(wi mod 2=1)((wi<L)∨(wi>R))∧(wi mod 2=0)((wi<L)∨(wi>R))∧(wi mod 2=1){A,(L≤wi≤R)∧(wi mod 2=0)T,(L≤wi≤R)∧(wi mod 2=1)G,((wi<L)∨(wi>R))∧(wi mod 2=0)C,((wi<L)∨(wi>R))∧(wi mod 2=1)
si=⎩⎪⎪⎪⎨⎪⎪⎪⎧A,T,G,C,(L≤wi≤R)∧(wi mod 2=0)(L≤wi≤R)∧(wi mod 2=1)((wi<L)∨(wi>R))∧(wi mod 2=0)((wi<L)∨(wi>R))∧(wi 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。第二行为一个仅包含A
、T
、G
、C
的一个序列 tt。
数据保证 0 < a < n,0<a<n, 0 \le b < n,0≤b<n, 0 \le L \le R < n,0≤L≤R<n, |t| \le 10^{6}∣t∣≤106,a,na,n 互质。
对于简单版本,1 \leq n \leq 10^{6}1≤n≤106;
对于中等版本,1 \leq n \leq 10^{9}, a = 11≤n≤109,a=1;
对于困难版本,1 \leq n \leq 10^{9}1≤n≤109。
输出格式
输出一个整数,为 tt 在 ss 中出现的次数。
样例说明
对于第一组样例,生成的 ss 为TTTCGGAAAGGCC
。
样例输入1
13 2 5 4 9 AGG
样例输出1
1
样例输入2
103 51 0 40 60 ACTG
样例输出2
5
模拟一遍题意 进行kmp算法 统计个数即可
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <string> using namespace std; const int MAX_N = 1e6+5; int Next[MAX_N]; char mo[MAX_N]; char str[MAX_N]; int w[MAX_N]; int n2,n1; void getnext(){ int i = 0,j = -1; while(i<n2){ if(j==-1||mo[i]==mo[j]){ ++i,++j,Next[i] = j; } else j=Next[j]; } return ; } int kmp(){ int cnt = 0; int i = 0,j = 0; while(i<n1){ if(j==-1||str[i]==mo[j]) i++,j++; else j = Next[j]; if(j==n2) cnt++; } return cnt; } int main(){ int a,b,L,R; scanf("%d%d%d%d%d",&n1,&a,&b,&L,&R); scanf("%s",mo); n2 = strlen(mo); w[0] = b; for(int i = 1;i<n1;++i){ w[i] = (w[i-1]+a)%n1 ; } for(int i=0;i<n1;++i){ if(w[i]<=R&&w[i]>=L){ if(w[i]%2==1) { str[i] = 'T'; continue; } else if(w[i]%2==0){ str[i]= 'A'; continue; } } else if(w[i]<L||w[i]>R){ if(w[i]%2==0){ str[i] = 'G'; continue; } else if(w[i]%2==1){ str[i] = 'C'; continue; } } } Next[0]=-1; getnext(); printf("%d\n",kmp()); return 0; }