POJ 2778 DNA Sequence

来源:互联网 发布:尼古丁口香糖 知乎 编辑:程序博客网 时间:2024/05/21 17:49

DNA Sequence

     自动机的又一题。这个题目和前面的那个题目POJ1625很相似,不过POJ1625的数据范围没有这么大,如果按照那个题目那样递推过来的话,肯定会超时。对于这么大的数据,一般会想到加速计算,多采用二分法,例如:快速幂取模,矩阵快速幂。而这个题目就是用矩阵快速幂来加速计算的。和前面一样我们可以很容易的写出状态转移方程,其实是一样的方程,这里就不再写了。我们把这个方程写成方程组的形式,那么我们就可以将这些方程组写成矩阵相乘的形式,那么我们就得到了通项公式,然后就是矩阵快速幂了。如果用递归的形式,貌似会RE,我写了一次结果RE了,换成非递归的就可以过了。当然如果取模次数太多的话,也是很容易超时的,取模的速度也是很慢的= . =,开始的时候貌似就在这个上面超了......

/*author: csuchenanLANG  : c++PROG  : POJ2778ALGORITHM: AC trie + DP + martix*/#include <cstdio>#include <cstring>#include <queue>using namespace std ;const int mod = 100000 ;int N ;int L ;struct Martix{    long long a[110][110] ;    int kbit ;};int next[110][4] ;int fail[110] ;bool flag[110] ;int cnt ;void debug(Martix E){    for(int i = 0 ; i <=E.kbit ; i ++){        printf("%d:" , i) ;        for(int j = 0 ;j <= E.kbit ; j ++){            printf("%d " , E.a[i][j]) ;        }        printf("\n") ;    }}inline void initMartix(Martix &E){    memset(E.a , 0 , sizeof(E.a)) ;    for(int i = 0 ; i < 110 ; i ++)        E.a[i][i] = 1 ;}inline void init(){    memset(next , 0 , sizeof(next)) ;    memset(fail , 0 , sizeof(fail)) ;    memset(flag , 0 , sizeof(flag)) ;    cnt = 0 ;}int hash(char c){    switch(c){        case 'A' : return 0 ;        case 'C' : return 1 ;        case 'G' : return 2 ;        case 'T' : return 3 ;    }}void insert(char * str){    char *p = str ;    int b;    int c(0) ;    while(*p){        b = hash(*p) ;        if(!next[c][b])            next[c][b] = ++ cnt ;        c = next[c][b] ;        p ++ ;    }    flag[c] = 1 ;}void build_ac(){    queue<int> Q ;    int cur(0) ;    int child  ;    fail[cur] = 0 ;    Q.push(cur) ;    while( !Q.empty() ){        cur = Q.front() ;        Q.pop() ;        for(int i = 0 ; i < 4 ; i ++){            child = next[cur][i] ;            if(child){                Q.push(child) ;                if(!cur)                    fail[cur] = 0 ;                else{                    int tmp = fail[cur] ;                    for(;tmp && !next[tmp][i] ; tmp = fail[tmp])                        ;                    if(next[tmp][i])                        fail[child] = next[tmp][i] ;                    else                        fail[child] = 0 ;                }                if(flag[fail[child]])                    flag[child] = 1 ;            }            else{                next[cur][i] = next[fail[cur]][i] ;            }        }    }}Martix build_martix(){    Martix ans ;    ans.kbit = cnt ;    memset(ans.a , 0 , sizeof(ans.a)) ;    for(int i = 0 ; i <= cnt ; i ++){        if(flag[i])            continue ;        for(int k = 0 ; k < 4 ; k ++){            int cur = next[i][k] ;            if(flag[cur])                continue ;            ans.a[ cur ][ i ] ++ ;        }    }    return ans ;}Martix mul(Martix A , Martix B){    int l = A.kbit ;    Martix ans ;    ans.kbit = l ;    for(int i = 0 ; i <= l ; i ++){        for(int j = 0 ; j <= l ; j ++){            int total ;            total = 0 ;            for(int k = 0 ; k <= l ; k ++){                total =( total + A.a[i][k]*B.a[k][j])%mod ;            }            ans.a[i][j] = total ;        }    }    return ans ;}Martix pow_martix(Martix A , int k){    Martix ans  ;    initMartix(ans) ;    ans.kbit = A.kbit;    while(k){        if(k&1)            ans = mul(ans , A) ;        A = mul(A , A) ;        k=k>>1 ;    }    return ans ;}/*Martix pow_martix(Martix A , int k){    Martix ans ;    ans.kbit = A.kbit ;    initMartix(ans) ;    if(k==0){        return ans ;    }    ans = pow_martix(A , k>>1) ;    ans = mul(ans , ans) ;    if(k&1)        ans = mul(ans , A) ;    return ans ;}*/void read(){    char str[15] ;    scanf("%d%d" , &N , &L) ;    for(int k = 1 ; k <= N ; k ++){        scanf("%s" , str) ;        insert(str) ;    }}inline void print(Martix A){    int ans(0);    for(int k = 0 ; k <= A.kbit ; k ++){        if(flag[k])            continue ;        ans = ans + A.a[k][0] ;    }    printf("%d\n" , ans%mod) ;}int main(){    //init() ;    read() ;    build_ac() ;    Martix E = build_martix() ;    Martix ans = pow_martix(E , L) ;    print(ans);    return 0 ;}