POJ 2778 DNA Sequence (Trie FIG matrix Fast Power)

Meaning of the questions:  give some viruses string length you ask consisting of n ATGC to these viruses do not contain the number of how many strings

 

analysis:

We first analyze the structure Tire chart: Trie FIG is to add on the prototype AC automatic machine side so that the state can be quickly transferred, labeled hazardous node (suffix node defective word); then we want configured length n does not comprise bad string right, it is not the number of programs in FIG trie n steps away from the secure node to node 0 (FIG Trie are state transition diagrams)

In a directed graph, A k-step walk to the number of Scheme B (which is obviously a classic matrix fast power issues), (principle needs its own search) to build a picture of the adjacent table M [i] [j], M [i] [j] = 1 i to j represents bordered directly connected, then ans = pow (M, k), ans [A] [B] as an answer

#include<queue>
#include<stdio.h>
#include<string.h>
using namespace std;

const int Max_Tot = 1e2 + 10;
const int Letter  = 4;
const int MOD = 1e5;
int maxn;
int mp[128];

struct mat{ int m[111][111]; }unit, M;

mat operator * (mat a, mat b)
{
    mat ret;
    long long x;
    for(int i=0; i<maxn; i++){
        for(int j=0; j<maxn; j++){
            x = 0;
            for(int k=0; k<maxn; k++){
                x += (long long)a.m[i][k]*b.m[k][j];
            }
            ret.m[i][j] = x % MOD;
        }
    }
    return ret;
}

inline void init_unit() { for(int i=0; i<maxn; i++) unit.m[i][i] = 1; }

mat pow_mat(mat a, int 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 = mp[s[i]];
            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;
    }

//1) If the Son [i] does not exist, it is now pointing to the current node pointer points fail
 // the successor node number i (guaranteed been calculated). 

// 2) If Son [i] is present, it will fail fail pointer to the current node is now
 // pointer to the successor node number i (guaranteed been calculated). 
    inline void BuildFail () { 
        the Node [ 0 ] .fail = 0 ;
         for ( int I = 0 ; I <Letter; I ++ ) {
             IF (the Node [ 0 ] .NEXT [I]) { 
                the Node [the Node [ 0 ] .NEXT [I]] = Fail. 0 ; 
                que.push (the Node [ 0 ] .NEXT [I]); 
            } the else the 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;

char S[11];
int main(void)
{
    mp['A']=0,
    mp['T']=1,
    mp['G']=2,
    mp['C']=3;
    int n, m;
    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();
//        for(int i=0; i<10; i++){
//            for(int j=0; j<10; j++){
//                printf("%d ", M.m[i][j]);
//            }puts("");
//        }puts("");

        init_unit();
        M = pow_mat(M, n);

//        for(int i=0; i<10; i++){
//            for(int j=0; j<10; j++){
//                printf("%d ", M.m[i][j]);
//            }puts("");
//        }puts("");

        int ans = 0;
        for(int i=0; i<ac.Size; i++)
            ans += M.m[0][i];
        ans %= MOD;
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

Guess you like

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