DNA Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11860 | Accepted: 4527 |
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
几个月没编AC自动机,突然编一下感觉之痛苦。
主要问题一点是fail指针构造时没有即使break掉,另一点是tail标记上传时需要加入一个while循环。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 100 #define MAXT 100 #define MOD 100000 typedef long long qword; struct trie_node { int ptr[4]; int fail; char w; bool tl; }trie[MAXT]; int topt=1; char str[MAXN]; void Add_word(char *str) { int now=1; int ind; while (*str) { ind=*(str++)-'A'; if (!trie[now].ptr[ind]) { trie[now].ptr[ind]=++topt; trie[topt].w=ind+'A'; trie[topt].tl=false; } now=trie[now].ptr[ind]; } trie[now].tl=true; } int q[MAXN]; void Build_Ac() { int head=-1,tail=0; int now,temp; int i,j; q[0]=1; trie[1].fail=1; while (head<tail) { now=q[++head]; for (i=0;i<4;i++) { if (!trie[now].ptr[i])continue; q[++tail]=trie[now].ptr[i]; if (now==1) { trie[trie[now].ptr[i]].fail=now; continue; } temp=trie[now].fail; while(temp!=1) { if (trie[temp].ptr[i]) { trie[trie[now].ptr[i]].fail=trie[temp].ptr[i]; break; } temp=trie[temp].fail; } if (!trie[trie[now].ptr[i]].fail) trie[trie[now].ptr[i]].fail=trie[1].ptr[i]; if (!trie[trie[now].ptr[i]].fail) trie[trie[now].ptr[i]].fail=1; } } for (i=1;i<=topt;i++) { for (j=0;j<4;j++) { if (!trie[i].ptr[j]) { temp=trie[i].fail; while (temp!=1) { if (trie[temp].ptr[j]) { trie[i].ptr[j]=trie[temp].ptr[j]; break; } temp=trie[temp].fail; } if (!trie[i].ptr[j]) trie[i].ptr[j]=trie[1].ptr[j]; if (!trie[i].ptr[j]) trie[i].ptr[j]=1; } } } j=3; while (j--) { for (i=0;i<=tail;i++) { if (trie[trie[i].fail].tl) trie[i].tl=true; } } } struct matrix { int n,m; qword a[MAXN][MAXN]; matrix() { memset(a,0,sizeof(a)); } void pm() { int i,j; for (i=1;i<=n;i++) { for (j=1;j<=m;j++) { printf("% 4d ",a[i][j]); } printf(" "); } printf(" "); } }m1,r1,m2; matrix operator *(matrix &m1,matrix &m2) { if (m1.m!=m2.n)throw 1; matrix ret; ret.n=m1.n; ret.m=m2.m; int i,j,k; for (i=1;i<=ret.n;i++) { for (j=1;j<=ret.m;j++) { for (k=1;k<=m1.m;k++) { ret.a[i][j]=(ret.a[i][j]+m1.a[i][k]*m2.a[k][j])%MOD; } } } return ret; } int main() { freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); int n,m,i,j,k,x,y,z; scanf("%d%d ",&m,&n); topt=1; trie[1].w='#'; for (i=0;i<m;i++) { scanf("%s",str); x=strlen(str); for (j=0;j<x;j++) { switch(str[j]) { case 'A':str[j]='A';break; case 'G':str[j]='B';break; case 'C':str[j]='C';break; case 'T':str[j]='D';break; } } Add_word(str); } Build_Ac(); m1.m=m1.n=topt; for (i=1;i<=topt;i++) { for (j=0;j<4;j++) { if (trie[trie[i].ptr[j]].tl)continue; m1.a[trie[i].ptr[j]][i]++; } } // m1.pm(); m2.m=1,m2.n=topt; m2.a[1][1]=1; while (n) { if (n&1) { m2=m1*m2; } m1=m1*m1; n>>=1; } /* for (i=1;i<=n;i++) { m2=m1*m2; // m2.pm(); }*/ qword ans=0; for (i=1;i<=topt;i++) { ans+=m2.a[i][1]; ans%=MOD; } printf("%d ",ans); return 0; }