DNA Sequence (AC自動機 矩陣快速冪)
阿新 • • 發佈:2019-02-16
DNA Sequence
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.
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.
Time Limit: 1000MS | Memory Limit: 65536K |
Total Submissions: 11450 | Accepted: 4357 |
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.
Input
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個DNA片段,然後問長度為m的DNA不包含所給DNA片段的DNA有多少種
01鄰接矩陣A的K次方C=A^K,C[i][j]表示i點到j點正好經過K條邊的路徑數
#include <cstdio> #include <iostream> #include <vector> #include <algorithm> #include <cstring> #include <string> #include <map> #include <cmath> #include <queue> #include <set> using namespace std; //#define WIN #ifdef WIN typedef __int64 LL; #define iform "%I64d" #define oform "%I64d\n" #define oform1 "%I64d" #else typedef long long LL; #define iform "%lld" #define oform "%lld\n" #define oform1 "%lld" #endif #define S64I(a) scanf(iform, &(a)) #define P64I(a) printf(oform, (a)) #define P64I1(a) printf(oform1, (a)) #define REP(i, n) for(int (i)=0; (i)<n; (i)++) #define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++) #define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++) const int INF = 0x3f3f3f3f; const double eps = 10e-9; const double PI = (4.0*atan(1.0)); const int MAX_NODE = 200 + 20; const int SIGMA_SIZE = 4; const int mod = 100000; struct Matrix { int n, m; LL mat[110][110]; Matrix(int n=0, int m=0) : n(n), m(m) { memset(mat, 0, sizeof(mat)); } }; struct ACAutomata { int ch[MAX_NODE][SIGMA_SIZE]; bool val[MAX_NODE]; int f[MAX_NODE]; int sz; void init() { sz = 1; memset(ch[0], -1, sizeof(ch[0])); val[0] = false; } int idx(char c) { if(c == 'A') return 0; if(c == 'C') return 1; if(c == 'T') return 2; if(c == 'G') return 3; } void insert(char * s) { int n = strlen(s); int u = 0; for (int i=0; i<n; i++) { int c = idx(s[i]); if(-1 == ch[u][c]) { memset(ch[sz], -1, sizeof(ch[sz])); val[sz] = false; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = true; } void build() { queue<int> Q; f[0] = 0; for (int i=0; i<SIGMA_SIZE; i++) { int u = ch[0][i]; if(u != -1) { Q.push(u); f[u] = 0; } else ch[0][i] = 0; } while (!Q.empty()) { int u = Q.front(); Q.pop(); if(val[f[u]]) val[u] = true; for (int c=0; c<SIGMA_SIZE; c++) { int v = ch[u][c]; if(-1 != v) { Q.push(v); f[v] = ch[f[u]][c]; } else { ch[u][c] = ch[f[u]][c]; } } } } Matrix getMatrix() { Matrix res(sz, sz); for(int i=0; i<sz; i++) { for(int j=0; j<4; j++) { int son = ch[i][j]; if(son >= 0 && !val[i] && !val[son]) { res.mat[i][son]++; } } } return res; } }; Matrix MatrixMult(Matrix m1, Matrix m2) { Matrix res(m1.n, m2.m); for(int i=0; i<res.n; i++) { for(int j=0; j<res.m; j++) { LL t = 0; for(int k=0; k<m1.m; k++) { t += m1.mat[i][k] * m2.mat[k][j]; t %= mod; } res.mat[i][j] = t; } } return res; } Matrix MatrixPowMod(Matrix A, int n) { Matrix di(A.n, A.n); REP(i, di.n) REP(j, di.n) di.mat[i][j] = i == j; while(n) { if(n&1) { di = MatrixMult(di, A); } A = MatrixMult(A, A); n >>= 1; } return di; } ACAutomata ac; char dic[1020][60]; char s[2000000 + 20]; int main() { int n, m; while(scanf("%d%d", &n, &m) != EOF) { ac.init(); for(int i=0; i<n; i++) { scanf("%s", dic[i]); ac.insert(dic[i]); } ac.build(); Matrix res = ac.getMatrix(); res = MatrixPowMod(res, m); LL ans = 0; for(int i=0; i<res.m; i++) { ans += res.mat[0][i]; ans %= mod; } P64I(ans); } return 0; }