DNA Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11143 | Accepted: 4259 |
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
POJ Monthly--2006.03.26,dodo
传送门:【POJ】2778 DNA Sequence
题目大意:给你m (m<= 10) 个非法串,每个串长度不超过10,且只用A,C,G,T四个字符,问长度为n(n <= 2000000000)的串中完全不包含上述非法串的个数(即合法串)。结果模100000。
题目分析:
比较好的一题AC自动机+矩阵加速。
首先构造出转移,对于合法的一个状态为i的串,如果添加一个字符以后便包含了任意一个非法串则称这个状态不可达,反之则可达,我们的目的就是要根据合法的转移确立解。
那么合法的转移该怎么得到?没错,通过AC自动机的Trie图的构造,我们可以得到一个转移图。其中每一个合法的转移都意味着一条路径,而我们的目的就是找到长度为n的路。需要注意的是如果某个转移对应的状态是整个非法串或者K次转移后是非法串,则该次转移是非法的。还有就是mod的数是100000。。。正好相乘爆int
代码如下:
传送门:【POJ】2778 DNA Sequence
题目大意:给你m (m<= 10) 个非法串,每个串长度不超过10,且只用A,C,G,T四个字符,问长度为n(n <= 2000000000)的串中完全不包含上述非法串的个数(即合法串)。结果模100000。
题目分析:
比较好的一题AC自动机+矩阵加速。
首先构造出转移,对于合法的一个状态为i的串,如果添加一个字符以后便包含了任意一个非法串则称这个状态不可达,反之则可达,我们的目的就是要根据合法的转移确立解。
那么合法的转移该怎么得到?没错,通过AC自动机的Trie图的构造,我们可以得到一个转移图。其中每一个合法的转移都意味着一条路径,而我们的目的就是找到长度为n的路。需要注意的是如果某个转移对应的状态是整个非法串或者K次转移后是非法串,则该次转移是非法的。还有就是mod的数是100000。。。正好相乘爆int
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( I , N ) for ( int I = 0 ; I < N ; ++ I )
#define CHARREP( I ) for ( int I = 0 ; buf[I] ; ++ I )
#define clear( A , X ) memset ( A , X , sizeof A )
const int maxW = 4 ;
const int maxM = 105 ;
const int mod = 100000 ;
const int maxQ = 1000000 ;
struct Matrix {
int mat[maxM][maxM] ;
int N ;
Matrix () {}
Matrix ( int n ) {
N = n ;
REP ( i , N ) REP ( j , N ) mat[i][j] = 0 ;
}
void Init () {
REP ( i , N ) mat[i][i] = 1 ;
}
Matrix operator * ( const Matrix &m ) const {
Matrix res = Matrix ( N ) ;
REP ( i , N ) REP ( j , N ) REP ( k , N )
res.mat[i][j] = ( res.mat[i][j] + ( long long ) mat[i][k] * m.mat[k][j] ) % mod ;
return res ;
}
} ;
struct Trie {
int next[maxM][maxW] ;
int fail[maxM] ;
int end[maxM] ;
int Q[maxQ] ;
int P , root ;
int head , tail ;
int New () {
REP ( i , maxW ) next[P][i] = -1 ;
end[P] = 0 ;
return P ++ ;
}
void Init () {
P = 0 ;
root = New () ;
}
int Get ( char x ) {
if ( x == 'A' ) return 0 ;
if ( x == 'C' ) return 1 ;
if ( x == 'G' ) return 2 ;
if ( x == 'T' ) return 3 ;
}
void Insert ( char buf[] ) {
int now = root ;
CHARREP ( i ) {
int x = Get ( buf[i] ) ;
if ( next[now][x] == -1 ) next[now][x] = New () ;
now = next[now][x] ;
}
end[now] = 1 ;
}
void Build () {
head = tail = 0 ;
fail[root] = root ;
REP ( i , maxW ) {
if ( next[root][i] == -1 ) next[root][i] = root ;
else {
fail[next[root][i]] = root ;
Q[tail ++] = next[root][i] ;
}
}
while ( head != tail ) {
int now = Q[head ++] ;
REP ( i , maxW ) {
if ( next[now][i] == -1 ) next[now][i] = next[fail[now]][i] ;
else {
fail[next[now][i]] = next[fail[now]][i] ;
end[next[now][i]] |= end[fail[next[now][i]]] ;
Q[tail ++] = next[now][i] ;
}
}
}
}
Matrix Matrix_Build () {
Matrix res = Matrix ( P ) ;
REP ( i , P ) REP ( j , maxW )
if ( !end[next[i][j]] ) ++ res.mat[i][next[i][j]] ;
return res ;
}
} ;
Trie AC ;
char buf[maxM] ;
Matrix Pow ( Matrix a , int n ) {
Matrix res = Matrix ( a.N ) ;
Matrix tmp = a ;
res.Init () ;
while ( n ) {
if ( n & 1 ) res = res * tmp ;
tmp = tmp * tmp ;
n >>= 1 ;
}
return res ;
}
void work () {
int m , n ;
while ( ~scanf ( "%d%d" , &m , &n ) ) {
AC.Init () ;
REP ( i , m ) {
scanf ( "%s" , buf ) ;
AC.Insert ( buf ) ;
}
AC.Build () ;
Matrix res = AC.Matrix_Build () ;
res = Pow ( res , n ) ;
int ans = 0 ;
REP ( i , res.N ) ans = ( ans + res.mat[0][i] ) % mod ;
printf ( "%d\n" , ans ) ;
}
}
int main () {
work () ;
return 0 ;
}