题目链接:2017计蒜客第一场
题目大意:
根据题目中给出的碱基序列的生成规则,求一个现有碱基序列在新得碱基序列中出现的次数
题目思路:
n比较大,暴力不可行,因此想到了kmp的方法,kmp复杂度O(n+m)
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 6000005
char s1[maxn],s2[maxn];
ll p[maxn],q[maxn],ans;
void print()
{
int i,j=0;
p[1]=0;
int len=strlen(s1+1);
for(i=2;i<=len;i++)
{
while(j>0 && s1[j+1]!=s1[i])
j=p[j];
if(s1[i]==s1[j+1])
j++;
p[i]=j;
}
}
void kmp()
{
int i,j=0,sum=strlen(s1+1);
int len=strlen(s2+1);
for(i=1;i<=len;i++)
{
while(j>0 && s2[i]!=s1[j+1])
j=p[j];
if(s1[j+1]==s2[i])
j++;
if(j==sum)
{
j=p[j];
ans++;
}
}
}
int main(void)
{
ll n,a,b,l,r,i,j;
scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&l,&r);
scanf("%s",s1+1);
for(i=0;i<n;i++)
{
if(i==0)
q[i]=b;
else
q[i]=(q[i-1]+a)%n;
if(q[i]>=l && q[i]<=r && q[i]%2==0)
s2[i+1]='A';
else if(q[i]>=l && q[i]<=r && q[i]%2==1)
s2[i+1]='T';
else if((q[i]<l || q[i]>r) && q[i]%2==0)
s2[i+1]='G';
else if((q[i]<l || q[i]>r) && q[i]%2==1)
s2[i+1]='C';
}
print();
kmp();
printf("%lld\n",ans);
return 0;
}