计蒜客 阿里天池的新任务(简单)KMP轻松水过

  • Post author:
  • Post category:其他


阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串 DNA 碱基序列


t








t




,判断它在另一个根据规则生成的 DNA 碱基序列


s








s




中出现了多少次。

首先,定义一个序列


w








w






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









w












i
















=




{















b


,











(



w












i





1
















+


a


)




m

od




n



,

























i


=


0











i


>


0




















接下来,定义长度为


n








n




的 DNA 碱基序列


s








s




(下标从


0








0




开始):



\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


,

























(


L






w












i



















R


)





(



w












i



















m


o


d






2



=


0


)











(


L






w












i



















R


)





(



w












i



















m


o


d






2



=


1


)











(


(



w












i
















<


L


)





(



w












i
















>


R


)


)





(



w












i



















m


o


d






2



=


0


)











(


(



w












i
















<


L


)





(



w












i
















>


R


)


)





(



w












i



















m


o


d






2



=


1


)




















其中


\land













表示“且”关系,


\lor













表示“或”关系,


a\ \mathrm{mod}\ b








a





m


o


d






b





表示


a








a




除以


b








b




的余数。

现给定另一个 DNA 碱基序列


t








t




,以及生成


s








s




的参数


n , a , b , L , R








n


,


a


,


b


,


L


,


R




,求


t








t







s








s




中出现了多少次。

输入格式

数据第一行为


5








5




个整数,分别代表


n , a , b , L , R








n


,


a


,


b


,


L


,


R




。第二行为一个仅包含

A



T



G



C

的一个序列


t








t




数据保证


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








1



0












6





















a,n








a


,


n




互质。

对于简单版本,


1 \leq n \leq 10^{6}








1





n





1



0












6


















对于中等版本,


1 \leq n \leq 10^{9}, a = 1








1





n





1



0












9
















,


a


=


1




对于困难版本,


1 \leq n \leq 10^{9}








1





n





1



0












9


















输出格式

输出一个整数,为


t








t







s








s




中出现的次数。

样例说明

对于第一组样例,生成的


s








s






TTTCGGAAAGGCC

样例输入1

13 2 5 4 9
AGG

样例输出1

1

样例输入2

103 51 0 40 60
ACTG

样例输出2

5

#include"iostream"
#include"cstring"
#define MAXX 1000000+5
using namespace std;
int w[MAXX];
char s[MAXX],t[MAXX];
int total=0;
void makeNext(char *pat,int next[])
{
	int len=strlen(pat),k=0,cur=1;
	
	next[0]=0;
	for(;cur<len;cur++)
	{
		while(k>0&&pat[k]!=pat[cur]) k=next[k-1];
		if(pat[k]==pat[cur]) k++;
		next[cur]=k;
	}	
}
void kmp(char *str,char *pat,int  next[])
{
	makeNext(pat,next);
	int str_len=strlen(str);
	int pat_len=strlen(pat);
	int k=0,cur=0;
	while(cur<str_len)
	{
		while(k>0&&pat[k]!=str[cur])k=next[k-1];
		if(pat[k]==str[cur]) k++;
		if(k==pat_len)
		{
			total++;
		} 
		cur++;
	}
}
int main()
{
	int n,a,b,l,r;
	int next[MAXX];
	cin>>n>>a>>b>>l>>r;
	cin>>t;
	for(int i=0;i<n;i++)
	{
		if(i==0)
		   w[i]=b;
		else
	    	w[i]=(w[i-1]+a)%n;
		if((w[i]>=l&&w[i]<=r)&&w[i]%2==0)
		   s[i]='A';
		else if((w[i]>=l&&w[i]<=r)&&w[i]%2==1)
		   s[i]='T';
		else if((w[i]<l||w[i]>r)&&w[i]%2==0)
		    s[i]='G';
		else if((w[i]<l||w[i]>r)&&w[i]%2==1)
		    s[i]='C';  
	}   
	kmp(s,t,next);
	cout<<total;
}



版权声明:本文为qq_33729889原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。