Poj 2778

Poj 2778
#include  < stdio.h >
#include 
< string .h >
#include 
< stdlib.h >
#include 
< algorithm >
#define  N 105
using   namespace  std;

struct  tree{
    tree 
* next[ 4 ],  * fail;
    
int  flag, num;
}
* root,  * p;

tree arr[
1000 ];
int  indexx;

int  map( char  ch){
    
if (ch  ==   ' A ' return   0 ;
    
if (ch  ==   ' C ' return   1 ;
    
if (ch  ==   ' T ' return   2 ;
    
if (ch  ==   ' G ' return   3 ;
}

void  newn(){
    arr[indexx].flag 
=   0 ;
    arr[indexx].num 
=  indexx;
    
for ( int  i  =   0 ; i  <   4 ; i  ++ ){
        arr[indexx].next[i] 
=   0 ;
    }
}

void  init(){
    indexx 
=   0 ;
    newn();
    root 
=   & arr[indexx ++ ];
}

void  insert( char  ch[],  int  w){
    
int  t, i  =   0 ;
    p 
=  root;
    
while (ch[i]){
        t 
=  map(ch[i]);
        
if (p -> next[t] == 0 ){
            newn();
            p
-> next[t]  =   & arr[indexx ++ ];
        }
        p 
=  p -> next[t];
        i 
++ ;
    }
    p
-> flag  =  w;
}

tree 
* que[ 10000 ];


bool  search(tree  * q)
{
    
while (q  !=  root)
    {
        
if (q -> flag)  return   true ;
        q 
=  q -> fail;
    }
    
return   false ;
}

void  get_fail(){
    p
= root;
    p
-> fail  =  root;
    
int  open  =   0 , close  =   - 1 , i;
    que[
0 =  p;
    
while (close  <  open){
        p 
=  que[ ++  close];
        tree 
* =  p;
        
int  pass  =   0 ;
        
if (q -> flag  ==   0 ) pass  =  search(q);
        
if (pass)    p -> flag  =   1 ;
        
for (i  =   0 ; i  <   4 ; i  ++ )
        {
            
if (p -> next[i]  ==   0 ){
                
if (p  ==  root)    p -> next[i]  =  root;
                
else             p -> next[i]  =  p -> fail -> next[i];
            }
            
else {
                
if (p  ==  root)    p -> next[i] -> fail  =  root;
                
else             p -> next[i] -> fail  =  p -> fail -> next[i];
                que[
++ open]  =  p -> next[i];
            }
        }
    }
}

long   long  n;
int  m;
long   long  f[N][N];

#define  M 100000

void  mod_multi( long   long  a[N][N],  long   long  b[N][N],  int  r){ // A=A*B%M A为r*r矩阵
     int  i, j, k;
    
long   long  c[N][N]  =  {};
    
for  (k  =   0 ; k  <  r; k ++ )
        
for  (i  =   0 ; i  <  r; i ++ )
            
for  (j  =   0 ; j  <  r; j ++ ){
                c[i][j] 
+=  a[i][k]  *  b[k][j];
                c[i][j] 
%=  M;
            }
    
for  (i  =   0 ; i  <  r; i ++ )
        
for  (j  =   0 ; j  <  r; j ++ )
            a[i][j] 
=  c[i][j];
}

void  mod_exp( long   long  a[N][N],  long   long  n,  int  r){ // A=A^n%m A为r*r矩阵
     int  i, j, k;
    
long   long  ans[N][N]  =  {};
    
for  (i  =   0 ; i  <  r; i ++ )ans[i][i]  =   1 // 单位阵
     for  (; n; n  >>=   1 ){
        
if  (n  &   1 )
            mod_multi(ans, a, r);
        mod_multi(a, a, r);
    }
    
for  (i  =   0 ; i  <  r; i ++ )
        
for  (j  =   0 ; j  <  r; j ++ )
            a[i][j] 
=  ans[i][j];
}


int  main(){
    
while (scanf( " %d %lld " & m,  & n)  !=  EOF){
        init();
        
char  str[ 12 ];
        
for ( int  i  =   0 ; i  <  m; i  ++ ){
            scanf(
" %s " , str);
            insert(str, 
1 );
        }
        get_fail();
        memset(f, 
0 sizeof (f));
        
for ( int  i  =   0 ; i  <  indexx; i  ++ ){
            
for ( int  j  =   0 ; j  <   4 ; j  ++ ){
                
if (arr[i].next[j] -> flag  ==   0   &&  arr[i].flag  ==   0 )
                    f[i][arr[i].next[j]
-> num]  ++ ;
            }
        }
        mod_exp(f, n, indexx);
        
long   long  ans  =   0 ;
        
for ( int  i  =   0 ; i  <  indexx; i  ++ ){
                ans 
+=  f[ 0 ][i];
                ans 
%=  M;
        }
        printf(
" %lld\n " , ans);
    }
}


另一个版本的比之高效很多
#include  < stdio.h >
#include 
< string .h >
#define  R 5
#define  N 105
#define  M 100000
typedef 
long   long  LL;

int  tree[N][R], flag[N], fail[N], state;
int  cha[ 128 =  {};

void  init(){
    cha[
' A ' =   1 ; cha[ ' T ' =   2 ;
    cha[
' G ' =   3 ; cha[ ' C ' =   4 ;
    memset(tree, 
- 1 sizeof (tree));
    memset(flag, 
0 sizeof (flag));
    memset(fail, 
- 1 sizeof (fail));
    flag[
0 =   0 ;
    state 
=   1 ;
}
void  insert( char  ch[]) {
    
int  p  =   0 , i  =   0 , t;
    
while (ch[i]) {
        t 
=  cha[ch[i]];
        
if (tree[p][t]  <   0 ) {
            flag[state] 
=   0 ;
            tree[p][t] 
=  state ++ ;
        }
        p 
=  tree[p][t];
        i 
++ ;
    }
    flag[p] 
=   1 ;
}

int  que[N];

void  get_fail() {
    
int  close  =   - 1 , open  =   0 ;
    que[
0 =   0 ;
    fail[
0 =   0 ;
    
while (close  <  open) {
        
int  p  =  que[ ++ close];
        
for ( int  i  =   0 ; i  <  R; i  ++ ) {
            
if (tree[p][i]  ==   - 1 ){
                
if (p  ==   0 )  tree[p][i]  =   0 ;
                
else         tree[p][i]  =  tree[fail[p]][i];
            } 
else  {
                
if (p  ==   0 )  fail[tree[p][i]]  =   0 ;
                
else         fail[tree[p][i]]  =  tree[fail[p]][i];
                que[
++ open]  =  tree[p][i];
            }
        }
    }
}
int  n, L;
LL f[N][N], sum 
=   0 ;

void  mod_multi(LL a[N][N], LL b[N][N],  int  r){
    
int  i, j, k;
    LL c[N][N] 
=  {};
    
for  (k  =   0 ; k  <  r; k ++ )
        
for  (i  =   0 ; i  <  r; i ++ )
            
if (a[i][k])
            
for  (j  =   0 ; j  <  r; j ++ ){
                c[i][j] 
+=  a[i][k]  *  b[k][j];
                c[i][j] 
%=  M;
            }
    
for  (i  =   0 ; i  <  r; i ++ )
        
for  (j  =   0 ; j  <  r; j ++ )
            a[i][j] 
=  c[i][j];
}

void  mod_exp(LL a[N][N], LL n,  int  r){
    
int  i, j, k;
    LL ans[N][N] 
=  {};
    
for  (i  =   0 ; i  <  r; i ++ )ans[i][i]  =   1 ;
    
for  (; n; n  >>=   1 ){
        
if  (n  &   1 )
            mod_multi(ans, a, r);
        mod_multi(a, a, r);
    }
    
for  (i  =   0 ; i  <  r; i ++ )
        
for  (j  =   0 ; j  <  r; j ++ )
            a[i][j] 
=  ans[i][j];
}

LL fast(LL sum, 
int  L) {
    LL temp 
=  1ll;
    
for (;L;L  >>=   1 ) {
        
if (L & 1 ) {
            temp 
*=  sum;
            temp 
%=  M;
        }
        sum 
*=  sum;
        sum 
%=  M;
    }
    
return  temp;
}

bool  search( int  q) {
    
while (q  !=   0 ) {
        
if (flag[q])  return   true ;
        q 
=  fail[q];
    }
    
return   false ;
}

int  main() {
    
while (scanf( " %d %d " & n , & L)  !=  EOF) {
        
char  str[ 11 ];
        init();
        
for ( int  i  =   0 ; i  <  n; i  ++ ) {
            scanf(
" %s " , str);
            insert(str);
        }
        get_fail();
        
int  map[N], cnt  =   0 , t;
        memset(map,
- 1 , sizeof (map));
        memset(f, 
0 sizeof (f));
        
for ( int  i  =   0 ; i  <  state; i  ++ ) {
            
if (flag[i]  ==   0 ) flag[i]  =  search(i);
        }
        
for ( int  i  =   0 ; i  <  state; i  ++ ) {
            
if (flag[i] == 0 )
            
for ( int  j  =   1 ; j  <  R; j  ++ ) {
                
if (flag[tree[i][j]]  ==   0 ) {
                    t 
=  tree[i][j];
                    
if (map[i]  ==   - 1 ) map[i]  =  cnt  ++ ;
                    
if (map[t]  ==   - 1 ) map[t]   =  cnt  ++ ;
                    f[map[i]][map[t]] 
++ ;
                }
            }
        }
        mod_exp(f, L, cnt);
        LL ans 
=   0 ;
        
for ( int  i  =   0 ; i  <  cnt; i  ++ ) {
            ans 
+=  f[ 0 ][i];
            ans 
%=  M;
        }
        printf(
" %lld\n " , ans);
    }
}


你可能感兴趣的:(Poj 2778)