DNA Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 13040 | Accepted: 4964 |
Description
It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For example, if a animal's DNA sequence contains segment ATC then it may mean that the animal may have a genetic disease. Until now scientists have found several those segments, the problem is how many kinds of DNA sequences of a species don't contain those segments.
Suppose that DNA sequences of a species is a sequence that consist of A, C, T and G,and the length of sequences is a given integer n.
Suppose that DNA sequences of a species is a sequence that consist of A, C, T and G,and the length of sequences is a given integer n.
Input
First line contains two integer m (0 <= m <= 10), n (1 <= n <=2000000000). Here, m is the number of genetic disease segment, and n is the length of sequences.
Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.
Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.
Output
An integer, the number of DNA sequences, mod 100000.
Sample Input
4 3 AT AC AG AA
Sample Output
36
Source
题目大意:长度为n不出现这些子串的个数。。
build_ac()的时候略有不同,
具体讲解,http://blog.csdn.net/acm_cxlove/article/details/7854526
看了好多代码,都不是很一样,看别人解析看了好久还是有些不大懂,主要是build_acde时候,找了一个和我写ac自动机比较像的大牛,按人家代码写了一下,先收藏一下吧
ac代码
#include<stdio.h>
#include<string.h>
#define mod 100000
char key[15];
int head,tail,cnt=0;
struct node
{
node *fail;
node *next[4];
int isword,kind;
}*q[500050],s[500050];
node *newnode()
{
node *temp=&s[cnt];
temp->fail=NULL;
temp->kind=cnt++;
for(int i=0;i<4;i++)
temp->next[i]=NULL;
return temp;
}
node *root;
int id(char c)
{
if(c=='A')
return 0;
else
if(c=='T')
return 1;
if(c=='C')
return 2;
return 3;
}
void insert(char *s)
{
int temp,len,i;
node *p=root;
len=strlen(s);
for(i=0;i<len;i++)
{
temp=id(s[i]);
if(p->next[temp]==NULL)
p->next[temp]=newnode();
p=p->next[temp];
}
p->isword=1;
}
void build_ac()
{
q[tail++]=root;
while(head!=tail)
{
node *p=q[head++];
node *temp=NULL;
for(int i=0;i<4;i++)
{
if(p->next[i]!=NULL)
{
if(p==root)
p->next[i]->fail=root;
else
{
temp=p->fail;
// while(temp!=NULL)
//{
// if(temp->next[i]!=NULL)
//{
p->next[i]->fail=temp->next[i];
// break;
//}
if(p->next[i]->fail->isword)
p->next[i]->isword=1;
//temp=temp->fail;
}
q[tail++]=p->next[i];
}
else
{
if(p==root)
p->next[i]=root;
else
{
p->next[i]=p->fail->next[i];
}
}
}
}
}
struct s
{
__int64 map[110][110];
}mm;
struct s muti(struct s a,struct s b)
{
struct s ans;
int i,j;
memset(ans.map,0,sizeof(ans.map));
int k;
for(i=0;i<cnt;i++)
{
for(k=0;k<cnt;k++)
{
if(a.map[i][k]!=0)
{
for(j=0;j<cnt;j++)
{
ans.map[i][j]+=a.map[i][k]*b.map[k][j];
if(ans.map[i][j]>=mod)
ans.map[i][j]%=mod;
}
}
}
}
return ans;
}
struct s qpow(struct s a,int n)
{
int i,j,k;
struct s ans;
// printf("MMMMMMMM\n");
memset(ans.map,0,sizeof(ans.map));
for(i=0;i<cnt;i++)
ans.map[i][i]=1;
while(n)
{
if(n&1)
ans=muti(ans,a);
a=muti(a,a);
n>>=1;
}
return ans;
}
int main()
{
int n,m;
while(scanf("%d%d",&m,&n)!=EOF)
{
int i,j;
head=tail=0;
cnt=0;
root=newnode();
for(i=0;i<m;i++)
{
scanf("%s",key);
insert(key);
}
build_ac();
memset(mm.map,0,sizeof(mm.map));
// printf("%d\n",cnt);
for(i=0;i<cnt;i++)
{
for(j=0;j<4;j++)
{
node *son=s[i].next[j];
if(!son->isword&&!s[i].isword)
{
mm.map[i][son->kind]++;
}
}
}
mm=qpow(mm,n);
__int64 ans=0;
for(i=0;i<cnt;i++)
{
// for(j=0;j<cnt;j++)
// {
ans+=mm.map[0][i];
ans%=mod;
// }
}
printf("%I64d\n",ans);
}
}