-----My AC Automaton-----
• Q: There are M-DNA sequences that are diseased and ask how many DNA sequences of length n do not contain any kind of disease-containing DNA sequence. (A,t,c,g four characters only) • Sample m=4,n=3,{"AA", "at", "AC", "AG"} the answer is 36, indicating that 36 sequences of length 3 can contain no disease
What does this have to do with matrices ...
• The above illustration is the example {"ACG", "C"}, after constructing the Trie diagram, as shown in the figure, there are 4 sides from each node (A,T,C,G) • There are 4 ways to go from State 0: – Walk A to State 1 (safe); – Go C to State 4 (danger); – Walk T to state 0 (safe);-Go G to the shape State 0 (security); * So when n=1, the answer is 3 when n=2, that is, from the state 0 Walk 2 steps, to form a length of 2 string, as long as the path is not through dangerous junction, there are several ways to go, then the answer is several. And so on, take n steps to form a string of length n. • Establish the adjacency matrix M of the trie graph:
2 1 0 0 1
2 1 1 0 0
1 1 0 1 1
2 1 0 0 1
2 1 0 0 1
M[I,J] means that there are several ways to take one step from the node I to the J.
Then the N-power of m means that there are several ways to move from the node I to the J step N.
Note: Dangerous nodes to be removed, that is, to remove dangerous nodes of the row and column. Nodes 3 and 4 are the end of the word so dangerous, node 2 of the fail pointer to 4, when matching "AC" also matches the "C", so 2 is also dangerous.
The Matrix becomes m:
2 1
2 1
Calculate m[][] n power, then Σ (M[0,i]) mod 100000 is the answer.
Because n is very large, you can use a binary to compute the power of a matrix.
#include <cstdio> #include <queue> #include <algorithm> #include <iostream> #include <
Cstring> using namespace std; const int MAX_N = 10 * 10 + 5; Maximum knot number: pattern string count X mode string max length const int cld_num = 4;
The most multilateral number from each node: The point is 4 ATCG typedef long Long matrix[max_n][max_n];
MATRIX Mat, MAT1, MAT2;
Long Long (*M1) [Max_n], (*M2) [Max_n]; Class Acautomaton {public:int n; Total number of current nodes int id[' Z ' +1]; The node number corresponding to the letter x is id[x] int fail[max_n]; Fail pointer bool Tag[max_n]; The required int trie[max_n][cld_num];
Trie tree void init () {id[' A '] = 0;
id[' T '] = 1;
id[' C '] = 2;
id[' G '] = 3;
void Reset () {memset (trie[0],-1, sizeof (trie[0));
Tag[0] = false;
n = 1;
//Insert pattern string s, construct word tree (keyword) void add (char *s) {int p = 0; while (*s) {int i = Id[*s];
if (-1 = trie[p][i]) {memset (Trie[n],-1, sizeof (TRIE[N)));
Tag[n] = false;
Trie[p][i] = n++;
} p = Trie[p][i];
s++;
} Tag[p] = true;
////using BFS to compute the fail pointer of each node, construct the trie tree Void construct () {queue<int> Q;
Fail[0] = 0; for (int i = 0; i < Cld_num i++) {if ( -1!= trie[0][i]) {fail[trie[0
][i]] = 0;
Q.push (Trie[0][i]); else {Trie[0][i] = 0; This cannot be lost} while (!
Q.empty ()) {int u = q.front ();
Q.pop (); if (Tag[fail[u]]) tag[u] = true; This is important when U's suffix is a virus and u cannot appear for (int i = 0; i < Cld_num; i++) {int &v = Trie[u
][i];
if (-1!= v) {Q.push (v);
FAIL[V] = Trie[fail[u]][i];
else {v = trie[fail[u]][i]; The adjacency matrix of the state transitions is constructed according to the trie Tree mat[][] mat[i][j] indicates the state I to the state J has several sides/void Buildmatrix
() {memset (mat, 0, sizeof (MAT)); for (int i = 0; i < n; i++) for (int j = 0; J < Cld_num; J +) if (!tag[i] &&!t
AG[TRIE[I][J]])//tag a node with a value of true cannot be, because the state of the node represents a virus mat[i][trie[i][j]]++;
} AC; void Matrixmult (Matrix t1, Matrix T2, matrix res) {for (int i = 0; i < AC.N; i++) for (int j = 0; J < A C.N;
J + +) {Res[i][j] = 0;
for (int k = 0; k < AC.N; k++) {Res[i][j] + = t1[i][k] * T2[k][j];
} Res[i][j]%= 100000; }/////////* Recursive binary computing matrix P-power, resulting in m2[][]/void matrixpower (intP) {if (p = = 1) {for (int i = 0; i < AC.N; i++) for (int j = 0; J < AC.N; J +)
M2[I][J] = Mat[i][j];
Return } matrixpower (P/2); The P/2 of the matrix is computed, and the result is m2[][] Matrixmult (M2, M2, M1); Calculates the square of the matrix m2, the result exists m1[][] if (p% 2)//if p is odd, then the matrix M1 multiplied by the original matrix mat[][], the result exists m2[]["Matrixmult" (M1, Mat
, m2);
Else swap (M1, M2);
int main () {int n, m;
Char s[12];
Ac.init ();
CIN >> m >> N;
Ac.reset ();
while (m--) {scanf ("%s", s);
Ac.add (s);
} ac.construct ();
Ac.buildmatrix ();
m1 = MAT1;
m2 = mat2;
Matrixpower (n);
int ans = 0;
for (int i = 0; i < AC.N i++) ans + = m2[0][i];
printf ("%d\n", ans% 100000);
return 0; }