HDU 2243 (Trie FIG matrix configuration and Power)

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 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

 

#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 ; 
}
View Code

 

Guess you like

Origin www.cnblogs.com/shuaihui520/p/11615477.html