Meaning of the questions: length does not exceed L, only lowercase letters, containing at least one root of the word, a total of how many might do? Here is not to consider whether the word meaningful.
For example, a total of 2 aa and ab & roots, there may be no longer than 3 104 words, respectively,
(2) aa, ab &,
(26 is th) AAA, AAB, AAC ... AAZ,
(26 is th) aba, ABB, abc ... ABZ,
(25 Ge) BAA, caa, daa ... zaa,
(25 Ge) bab, cab, dab ... zab
Analysis: We may Matrix fast power run by Tire map, to seek length n does not contain a word given word to sum; so expect demand: the length n contain a word given word algorithm is to use the overall program number - n is the length of a given word does not contain the word program number 26 ^ n-sum; this difficult problem is to find the length L does not exceed the number of programs, that we request 26-sum1 + 26 ^ 2-sum2 + 26 ^ 3-sum3 ...... 26 ^ n-sumn = (26 + 26 ^ 2 + ... 26 ^ n) - (sum1 + sum2 + ... sumn); we obviously are not required to traverse; priority consideration algorithm:
Trie FIG assumption that the original state matrix is constructed out of A, then we need to construct the same and a power i.e. A . 1 + A 2 + A . 3 + ..... + A L and the final answer is [Sigma L (0 , i) (i ∈ 1 ~ matrix length), then how to construct these two powers and it?
As long as you can use this formula with the original matrix + matrix + zero matrix construct a new matrix, the matrix is finally the upper right corner of powers and the matrix
The method of construction (1) in solving (26 + 26 ^ 2 + ... 26 ^ n) when the geometric series formula can not be used to seek, the error will be so, can use the above configuration of the matrix: The points to note
| 26,1 |
| 0, 1 | run fast power matrix
(2 ^ 64 for power modulo 2) open directly unsigned long long enough
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<string.h> #include<stdio.h> #include<iostream> #include<queue> #define ULL unsigned long long using namespace std; const int Max_Tot = 1e2 + 10; const int Letter = 26; int maxn;///矩阵的大小 char S[11]; struct mat{ ULL m[111][111]; }unit, M; mat operator * (mat a, mat b){ mat ret; for(int i=0; i<maxn; i++){ for(int j=0; j<maxn; j++){ ret.m[i][j] = (ULL)0; for(int k=0; k<maxn; k++){ ret.m[i][j] += a.m[i][k]*b.m[k][j]; } } } return ret; } inline void init_unit() { for(int i=0; i<maxn; i++) unit.m[i][i] = 1; } mat pow_mat(mat a, long long n){ mat ret = unit; while(n){ if(n&1) ret = ret * a; a = a*a; n >>= 1; } return ret; } struct Aho{ struct StateTable{ int Next[Letter]; int fail, flag; }Node[Max_Tot]; int Size; queue<int> que; inline void init(){ while(!que.empty()) que.pop(); memset(Node[0].Next, 0, sizeof(Node[0].Next)); Node[0].fail = Node[0].flag = 0; Size = 1; } inline void insert(char *s){ int now = 0; for(int i=0; s[i]; i++){ int idx = s[i] - 'a'; if(!Node[now].Next[idx]){ memset(Node[Size].Next, 0, sizeof(Node[Size].Next)); Node[Size].fail = Node[Size].flag = 0; Node[now].Next[idx] = Size++; } now = Node[now].Next[idx]; } Node[now].flag = 1; } inline void BuildFail(){ Node[0].fail = -1; for(int i=0; i<Letter; i++){ if(Node[0].Next[i]){ Node[Node[0].Next[i]].fail = 0; que.push(Node[0].Next[i]); }else Node[0].Next[i] = 0;///必定指向根节点 } while(!que.empty()){ int top = que.front(); que.pop(); if(Node[Node[top].fail].flag) Node[top].flag = 1; for(int i=0; i<Letter; i++){ int &v = Node[top].Next[i]; if(v){ que.push(v); Node[v].fail = Node[Node[top].fail].Next[i]; }else v = Node[Node[top].fail].Next[i]; } } } inline void BuildMatrix(){ for(int i=0; i<Size; i++) for(int j=0; j<Size; j++) M.m[i][j] = 0; for(int i=0; i<Size; i++){ for(int j=0; j<Letter; j++){ if(!Node[i].flag && !Node[ Node[i].Next[j] ].flag) M.m[i][Node[i].Next[j]]++; } } maxn = Size; } } ac; ULL GetSum ( Long Long num) { matte; ret.m [ 0 ] [ 0 ] = 26 ; ret.m [ 0 ] [ 1 ] = 1 ; ret.m [ 1 ] [ 0 ] = 0 ; ret.m [ 1 ] [ 1 ] = 1 ; int tmp = maxn; maxn = 2 ; right = pow_mat (right ++ num); maxn = tmp; return ret.m [ 0 ] [ . 1 ] - . 1 ; } ULL GetElimination ( Long Long NUM) { MAT tmp; for ( int I = 0 ; I <MAXN; I ++) /// upper left corner of the original matrix for ( int J = 0 ; J <MAXN; J ++ ) tmp.m [I] [J] = of Mm [I] [J]; for ( int I = 0 ; I <MAXN; I ++) /// top right corner of a unit matrix for ( int J = MAXN; J <(MAXN << . 1 ); J ++ ) tmp.m [I] [J] = (I + MAXN == J); for ( int I = MAXN; I <(MAXN << . 1 ); I ++) /// lower left corner of the matrix is zero for ( int J = 0 ; J <MAXN; J ++ ) tmp.m [I] [J] = 0 ; for ( int I = MAXN; I <(MAXN << . 1 ); I ++) /// lower right corner of a unit matrix for ( int J MAXN =; J <(MAXN << . 1 ); J ++ ) tmp.m [I] [J] = (I == J); int the Temp = MAXN; MAXN << = . 1 ; /// first original matrix size enlarged twice as fast computing power, and the power of writing about my fast tmp = pow_mat (tmp, ++ NUM); ULL RET = (ULL) 0 ; MAXN = TEMP; /// then return to the original size for ( int I = MAXN; I <(MAXN << . 1 ); I ++) /// matrix and the upper right corner is the power RET = tmp.m + [ 0 ] [I ]; return (--ret); /// need -1 } int main ( void ) { int n-, m; the while (~ Scanf ( " % D% D " , & m, & n-)) { ac.init (); for ( int I = 0 ; I <m; I ++ ) { Scanf ( " % S " , S); ac.insert (S); } ac.BuildFail (); ac.BuildMatrix (); init_unit (); ULL Tot = GetSum (( Long Long ) n-); /// note is passed or will burst long long int ULL = GetElimination Elimination (( Long Long ) n-); COUT << Tot-Elimination << endl; } return 0 ; }