Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 10031 | Accepted: 3762 |
Description
Input
Output
Sample Input
4 3 AT AC AG AA
Sample Output
36
#include <cstdio> #include <cstring> const int NODE = 105; const int CH = 4; const int mod = 100000; int chd[NODE][CH], sz = 1; int word[NODE]; int fail[NODE]; int que[NODE]; int sw[128]; //AC自动机部分 void Ins( char* a ) { int p = 0; while( *a ) { int c = sw[*a]; if( !chd[p][c] ) { memset( chd[sz], 0, sizeof(chd[sz]) ); word[sz] = 0; chd[p][c] = sz++; } p = chd[p][c]; a++; } word[p] = 1; } void AC( ) { int *s = que, *e = que; for( int i = 0; i < CH; ++i ) if( chd[0][i] ) { fail[chd[0][i]] = 0; *e++ = chd[0][i]; } while( s != e ) { int p = *s++; for( int i = 0; i < CH; ++i ) { if( chd[p][i] ) { int v = chd[p][i]; *e++ = v; fail[v] = chd[fail[p]][i]; word[chd[p][i]] |= word[chd[fail[p]][i]]; } else chd[p][i] = chd[fail[p]][i]; } } } //矩阵部分 class matrix { public: __int64 num[NODE][NODE]; int r, l; matrix( int rr = 0, int ll = 0 ) { r = rr; l = ll; memset(num, 0, sizeof(num)); } matrix operator*( matrix& a ) { int i, j, k; matrix result( r, a.l ); for( i = 0; i < r; ++i ) for( j = 0; j < a.l; ++j ) { result.num[i][j] = 0; //注意这里,如果一边加一边取余的话会很慢··· //POJ上用C++提交,一边加一边取余,刚好1000MS压过,换这样就200MS+ for( k = 0; k < l; ++k ) result.num[i][j] += num[i][k]*a.num[k][j]; result.num[i][j] %= mod; } return result; } }; //构造矩阵m,m[i][j]表示从状态i转移到状态j的方法数 void get_matrix( matrix& m ) { int i, j; for( i = 0; i < sz; ++i ) if( !word[i] ) { for( j = 0; j < CH; ++j ) { if( !word[chd[i][j]] ) m.num[i][chd[i][j]]++; } } } int main() { int m, n, i, ans = 0; char s[20]; fail[0] = 0; sw['A'] = 0; sw['C'] = 1; sw['G'] = 2; sw['T'] = 3; memset(chd[0], 0, sizeof(chd[0])); scanf("%d %d", &m, &n); while( m-- ) { scanf("%s", s); Ins(s); } AC(); matrix mat( sz, sz ); get_matrix( mat ); matrix mm = mat; //矩阵幂乘 --n; while( n ) { if( n % 2 ) mat = mat * mm; mm = mm * mm; n /= 2; } for( i = 0; i < sz; ++i ) ans += mat.num[0][i]; printf("%d\n", ans%mod); return 0; }