POJ2778ac自动机+矩阵加速

来源:互联网 发布:找不到网络控制器 编辑:程序博客网 时间:2024/04/29 06:55

求长度为M的DNA串不包含模式串的有多少个。

    step1::先考虑另外一个问题,给你一个有向图,从某个点出发走n步到其他任意点,问不同的走法。

  对这个问题构造一个矩阵,matrix[i][j]表示从i到j有几条边,然后这个矩阵自乘n次就是答案。

     step2 :      点击打开链接

                        点击打开链接

    


2张图片均转自上述衔接博客,感谢。


typedef long long LL ;const   LL   mod = 100000 ;int     matn ;struct  Mat{        LL x[108][108] ;        Mat(){             memset(x , 0 , sizeof(x)) ;        }        Mat(int){             memset(x , 0 , sizeof(x)) ;             for(int i = 0 ; i < matn ; i++)                 x[i][i] = 1 ;        }};Mat operator * (Mat a , Mat b){        Mat s ;        int n = matn  , i , j , k ;        for(i = 0 ; i < n ; i++){            for(j = 0 ; j < n ; j++){                if(a.x[i][j] == 0) continue ;                for(k = 0 ; k < n ; k++){                     s.x[i][k] += a.x[i][j] * b.x[j][k] ;                     s.x[i][k] %= mod ;                }            }        }        return s ;}Mat  Pow(Mat x , int y){     Mat s(1) ;     for(; y ; y >>= 1){          if(y & 1) s = s * x ;          x = x * x ;     }     return s ;}/*AC-------------*/const  int maxn = 108*4 ;const  int kind = 4 ;int    next[maxn][kind] ;int    fail[maxn] ;int    id[maxn]   ;struct  AC{        int  root , n ;        int  newnode(){             id[n] = 0 ;             for(int i = 0 ; i < kind ; i++) next[n][i] = -1 ;             return n++ ;        }        void  Init(){              n = 0 ;              root = newnode() ;        }        int   to(char c){              if(c == 'A') return 0 ;              else if(c == 'C') return 1 ;              else if(c == 'T') return 2 ;              else return 3 ;        }        void  Insert(char *s){              int now = root  , k ;              while(*s){                   k = to(*s) ;                   if(next[now][k] == -1)                       next[now][k] = newnode() ;                   now = next[now][k] ;                   s++ ;              }              id[now] = 1  ;        }        void  makeAc(){              queue<int> q ;              fail[root] = root ;              int now , i ;              for(i = 0 ; i < kind ; i++){                   if(next[root][i] == -1)                       next[root][i] = root ;                   else{                       fail[next[root][i]] =  root ;                       q.push(next[root][i]) ;                   }              }              while(! q.empty()){                   now = q.front() ; q.pop() ;                   if(id[fail[now]] == 1)  id[now] = 1 ;                   for(i = 0 ; i < kind ; i++){                       if(next[now][i] == -1)                           next[now][i] = next[fail[now]][i] ;                       else{                           fail[next[now][i]] = next[fail[now]][i] ;                           q.push(next[now][i]) ;                       }                   }              }        }        Mat  getMat(){             matn = n ;             Mat s ;             for(int i = 0 ; i < n ; i++){                 if(id[i]) continue ;                 for(int j = 0 ; j < kind ; j++){                      if(id[next[i][j]] == 0){                           s.x[i][next[i][j]]++ ;                      }                 }             }             return s ;        }}ac ;/*EndAc---------------*/char  word[18] ;int   main(){      int t , n  , i  , m  ,j ;      while(cin>>n>>m){           ac.Init() ;           for(i = 1 ; i <= n ; i++){                scanf("%s" , word) ;                ac.Insert(word) ;           }           ac.makeAc() ;           Mat a = ac.getMat() ;           a = Pow(a , m) ;           LL sum = 0 ;           for(i = 0 ; i < matn ; i++){               sum += a.x[0][i] ;               sum %= mod ;           }           cout<<sum<<endl ;      }      return 0 ;}


0 0
原创粉丝点击