问题描述
阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串碱基序列 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;
}