This question is quite classic.
First, it is the process of creating an automatic machine. In fact, it is a state transfer. If a substring in a dictionary tree is added with a letter, it will become an invalid string and then be marked.
Finally, we can see how many States there are and how many matrices are created. For a certain State, if a letter is added, the state can be transferred. The position in the corresponding matrix is ++.
Then there is a matrix multiplication. After k times, the matrix x [I] [j] indicates the number of transition lengths from the I state to the j state path to k, the final result is the sum from 0 to all States.
It is important to note that the modulo operation takes a lot of time and can be minimized.
[Cpp]
Include <iostream>
# Include <algorithm>
# Include <cstring>
# Include <string>
# Include <cstdio>
# Include <cmath>
# Include <queue>
# Include <map>
# Include <set>
# Define eps 1e-5
# Define maxn155
# Define MAXM 40000
# Define INF 1000000001
# Define lch (x) x <1
# Define rch (x) x <1 | 1
# Define lson l, m, rt <1
# Define rson m + 1, r, rt <1 | 1
Using namespace std;
Int h [155];
Int n, m, e;
Long mat [MAXN] [MAXN], ans [MAXN] [MAXN];
Struct Trie
{
Int next [4];
Int fail, flag;
Void init ()
{
Memset (next, 0, sizeof (next ));
Fail =-1;
Flag = 0;
}
} Trie [MAXM];
Void init ()
{
For (int I = 0; I <MAXM; I ++) trie [I]. init ();
E = 0;
Memset (mat, 0, sizeof (mat ));
Memset (ans, 0, sizeof (ans ));
}
Void make_trie (char * str)
{
Int I = 0, index, u = 0;
While (str [I])
{
Index = h [str [I];
If (! Trie [u]. next [index]) trie [u]. next [index] = ++ e;
U = trie [u]. next [index];
I ++;
}
Trie [u]. flag = 1;
}
Int q [MAXM];
Void make_ac_automation ()
{
Int h = 0, t = 0;
Q [t ++] = 0;
While (h <t)
{
Int u = q [h ++], v, j;
For (int I = 0; I <4; I ++)
{
If (trie [u]. next [I])
{
V = trie [u]. next [I];
J = trie [u]. fail;
While (j! =-1 &&! Trie [j]. next [I]) j = trie [j]. fail;
If (j =-1) trie [v]. fail = 0;
Else
{
Trie [v]. fail = trie [j]. next [I];
Trie [v]. flag | = trie [trie [v]. fail]. flag;
}
Q [t ++] = v;
}
Else
{
J = trie [u]. fail;
While (j! =-1 &&! Trie [j]. next [I]) j = trie [j]. fail;
If (j =-1) trie [u]. next [I] = 0;
Else trie [u]. next [I] = trie [j]. next [I];
}
}
}
}
Long z [MAXN] [MAXN];
Long mod = 100000;
Void multiply (long x [MAXN] [MAXN], long y [MAXN] [MAXN])
{
For (int I = 0; I <= e; I ++)
{
For (int j = 0; j <= e; j ++)
{
Z [I] [j] = 0;
For (int k = 0; k <= e; k ++)
Z [I] [j] = z [I] [j] + x [I] [k] * y [k] [j];
Z [I] [j] % = mod;
}
}
For (int I = 0; I <= e; I ++)
For (int j = 0; j <= e; j ++)
Y [I] [j] = z [I] [j];
}
Int main ()
{
Init ();
H ['a'] = 0, h ['T'] = 1, h ['G'] = 2, h ['C'] = 3;
Scanf ("% d", & m, & n );
Char str [25];
For (int I = 0; I <m; I ++)
{
Scanf ("% s", str );
Make_trie (str );
}
Make_ac_automation ();
For (int I = 0; I <= e; I ++)
If (trie [I]. flag = 0)
For (int j = 0; j <4; j ++)
If (trie [trie [I]. next [j]. flag = 0)
Mat [I] [trie [I]. next [j] ++;
For (int I = 0; I <= e; I ++) ans [I] [I] = 1;
While (n)
{
If (n & 1) multiply (mat, ans );
Multiply (mat, mat );
N> = 1;
}
Long res = 0;
For (int I = 0; I <= e; I ++) res = res + ans [0] [I];
Printf ("% I64d \ n", res % mod );
Return 0;
}
# Include <iostream>
# Include <algorithm>
# Include <cstring>
# Include <string>
# Include <cstdio>
# Include <cmath>
# Include <queue>
# Include <map>
# Include <set>
# Define eps 1e-5
# Define maxn155
# Define MAXM 40000
# Define INF 1000000001
# Define lch (x) x <1
# Define rch (x) x <1 | 1
# Define lson l, m, rt <1
# Define rson m + 1, r, rt <1 | 1
Using namespace std;
Int h [155];
Int n, m, e;
Long mat [MAXN] [MAXN], ans [MAXN] [MAXN];
Struct Trie
{
Int next [4];
Int fail, flag;
Void init ()
{
Memset (next, 0, sizeof (next ));
Fail =-1;
Flag = 0;
}
} Trie [MAXM];
Void init ()
{
For (int I = 0; I <MAXM; I ++) trie [I]. init ();
E = 0;
Memset (mat, 0, sizeof (mat ));
Memset (ans, 0, sizeof (ans ));
}
Void make_trie (char * str)
{
Int I = 0, index, u = 0;
While (str [I])
{
Index = h [str [I];
If (! Trie [u]. next [index]) trie [u]. next [index] = ++ e;
U = trie [u]. next [index];
I ++;
}
Trie [u]. flag = 1;
}
Int q [MAXM];
Void make_ac_automation ()
{
Int h = 0, t = 0;
Q [t ++] = 0;
While (h <t)
{
Int u = q [h ++], v, j;
For (int I = 0; I <4; I ++)
{
If (trie [u]. next [I])
{
V = trie [u]. next [I];
J = trie [u]. fail;
While (j! =-1 &&! Trie [j]. next [I]) j = trie [j]. fail;
If (j =-1) trie [v]. fail = 0;
Else
{
Trie [v]. fail = trie [j]. next [I];
Trie [v]. flag | = trie [trie [v]. fail]. flag;
}
Q [t ++] = v;
}
Else
{
J = trie [u]. fail;
While (j! =-1 &&! Trie [j]. next [I]) j = trie [j]. fail;
If (j =-1) trie [u]. next [I] = 0;
Else trie [u]. next [I] = trie [j]. next [I];
}
}
}
}
Long z [MAXN] [MAXN];
Long mod = 100000;
Void multiply (long x [MAXN] [MAXN], long y [MAXN] [MAXN])
{
For (int I = 0; I <= e; I ++)
{
For (int j = 0; j <= e; j ++)
{
Z [I] [j] = 0;
For (int k = 0; k <= e; k ++)
Z [I] [j] = z [I] [j] + x [I] [k] * y [k] [j];
Z [I] [j] % = mod;
}
}
For (int I = 0; I <= e; I ++)
For (int j = 0; j <= e; j ++)
Y [I] [j] = z [I] [j];
}
Int main ()
{
Init ();
H ['a'] = 0, h ['T'] = 1, h ['G'] = 2, h ['C'] = 3;
Scanf ("% d", & m, & n );
Char str [25];
For (int I = 0; I <m; I ++)
{
Scanf ("% s", str );
Make_trie (str );
}
Make_ac_automation ();
For (int I = 0; I <= e; I ++)
If (trie [I]. flag = 0)
For (int j = 0; j <4; j ++)
If (trie [trie [I]. next [j]. flag = 0)
Mat [I] [trie [I]. next [j] ++;
For (int I = 0; I <= e; I ++) ans [I] [I] = 1;
While (n)
{
If (n & 1) multiply (mat, ans );
Multiply (mat, mat );
N> = 1;
}
Long res = 0;
For (int I = 0; I <= e; I ++) res = res + ans [0] [I];
Printf ("% I64d \ n", res % mod );
Return 0;
}