zoukankan      html  css  js  c++  java
  • 【POJ2778】DNA Sequence 【AC自动机,dp,矩阵快速幂】

    题意

      题目给出m(m<=10)个仅仅由A,T,C,G组成的单词(单词长度不超过10),然后给出一个整数n(n<=2000000000),问你用这四个字母组成一个长度为n的长文本,有多少种组成方法可以使得它不含任何一个给出的单词。

    分析

      当时一看以为是跟训练指南上(UVA11468)一样的题,感觉只有四个字母并且单词数量和长度也比较小,但是一看给出的n有点懵逼。如果再按照书上建立AC自动机以后直接跑DP的方法肯定是不行了。然后我们就要用到,递推利器,矩阵快速幂。

      我们还是按照套路先把AC自动机建出来,然后将每个单词结点设为非法结点,题目变成在AC自动机中走n步不通过非法结点的方案数。然后设f[i][j]是当前在结点i,已经走了j步,且未走过非法结点的方案数。然后怎么转移呢?

      f[i][j]=A(0,i)*f[0][j-1]+A(1,i)*f[1][j-1]+...+A(sz-1,i)f[sz-1][j-1]。其中A(i,j)的含义就是从i到j有几条直接连接的边。那么将这个dp方程拆开来看

      

      f0[i]=A(0,0)*f[0][i-1]+A(1,0)*f[1][i-1]+....+A(sz-1,0)*fsz-1[i-1]

      f1[i]=A(0,1)*f[0][i-1]+A(1,1)*f[1][i-1]+....+A(sz-1,1)*fsz-1[i-1]

      .

      .

      fsz-1[i]=A(0,sz-1)*f[0][i-1]+A(1,sz-1)*f[1][i-1]+...+A(sz-1,sz-1)*fsz-1[i-1]

     然后根据这个我们就很好建立转移矩阵

     *

      (第一次学会用公式编辑器不过好像还是贼丑)

       然后建立这个大的转移矩阵,矩阵的(i,j)为结点i到结点j的直接路径的条数,然后跑一个矩阵快速幂。 

       最后把从0到sz-1结点的f(n)的值全部加起来就是答案了。

        对了这个题需要用long long

       下面是代码

       

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <iostream>
      5 #include <queue>
      6 #include <map>
      7 
      8 using namespace std;
      9 const int maxnode=1100;
     10 const int MOD=100000;
     11 map<char,int>M;
     12 struct AC_Automata{
     13     int ch[maxnode][4],f[maxnode],last[maxnode],val[maxnode],match[maxnode];
     14     int sz;
     15     int idx(char c){
     16         return M[c];
     17     }
     18     void init(){
     19         sz=1;
     20         memset(ch[0],0,sizeof(ch[0]));
     21         memset(match,0,sizeof(match));
     22         val[0]=0;
     23     }
     24     void insert(char *s){
     25         int n=strlen(s),u=0;
     26         for(int i=0;i<n;i++){
     27             int c=idx(s[i]);
     28             if(!ch[u][c]){
     29                 ch[u][c]=sz;
     30                 memset(ch[sz],0,sizeof(ch[sz]));
     31                 val[sz++]=0;
     32             }
     33             u=ch[u][c];
     34         }
     35         val[u]=1;
     36         match[u]=1;
     37     }
     38     void getFail(){
     39         queue<int>q;
     40         last[0]=f[0]=0;
     41         for(int i=0;i<4;i++){
     42             int u=ch[0][i];
     43             if(u){
     44                 q.push(u);
     45                 f[u]=last[u]=0;
     46             }
     47         }
     48         while(!q.empty()){
     49             int r=q.front();q.pop();
     50             for(int i=0;i<4;i++){
     51                 int u=ch[r][i];
     52                 if(!u){
     53                     ch[r][i]=ch[f[r]][i];
     54                     continue;
     55                 }
     56                 q.push(u);
     57                 int v=f[r];
     58                 while(v&&!ch[v][i])v=f[v];
     59                 f[u]=ch[v][i];
     60                 match[u]|=match[f[u]];
     61             }
     62         }
     63     }
     64 }ac;
     65 const int maxN=101;
     66 struct Matrix{
     67     long long a[maxN][maxN];
     68     void init(){
     69         memset(a,0,sizeof(a));
     70         for(int i=0;i<ac.sz;i++)
     71             a[i][i]=1;
     72     }
     73 };
     74 Matrix mul(Matrix a,Matrix b){
     75     Matrix res;
     76     for(int i=0;i<ac.sz;i++){
     77         for(int j=0;j<ac.sz;j++){
     78             res.a[i][j]=0;
     79             for(int k=0;k<ac.sz;k++){
     80                 res.a[i][j]+=a.a[i][k]*b.a[k][j];
     81                 res.a[i][j]%=MOD;
     82             }
     83         }
     84     }
     85     return res;
     86 }
     87 Matrix qpow(Matrix a,int k){
     88     Matrix res;
     89     res.init();
     90     while(k){
     91         if(k%2)res=mul(res,a);
     92         a=mul(a,a);
     93         k/=2;
     94     }
     95     return res;
     96 }
     97 int n,m;
     98 char s[30];
     99 
    100 int main(){
    101     M['A']=0,M['C']=1,M['T']=2,M['G']=3;
    102     ac.init();
    103     scanf("%d%d",&m,&n);
    104     for(int i=1;i<=m;i++){
    105         scanf("%s",s);
    106         ac.insert(s);
    107     }
    108     ac.getFail();
    109     Matrix A;
    110     for(int i=0;i<ac.sz;i++){
    111             if(!ac.match[i])
    112         for(int j=0;j<4;j++){
    113             int u=ac.ch[i][j];
    114             if(!ac.match[u])
    115             A.a[i][u]++;
    116         }
    117     }
    118     /*for(int i=0;i<ac.sz;i++){
    119         for(int j=0;j<ac.sz;j++){
    120             printf("%d ",A.a[i][j]);
    121         }
    122         printf("
    ");
    123     }*/
    124 
    125     Matrix S;
    126     S.a[0][0]=1;
    127     Matrix ANS;
    128     ANS=qpow(A,n);
    129     ANS=mul(S,ANS);
    130     long long ans=0; 
    131     for(int i=0;i<=ac.sz;i++)
    132         ans+=ANS.a[0][i];
    133     printf("%d
    ",ans%MOD);
    134 return 0;
    135 }
    View Code
  • 相关阅读:
    构建业务用例
    CentOS 7使用Redis Cluster
    pymysql.err.OperationalError: (1054, "Unknown column 'aa' in 'field list'")(已解决)
    Flask框架实现登录注册功能(mysql数据库)
    C#实现登录功能(连接SQLServer数据库)
    大数据智能加工系统——纸上原型分析
    Windows环境下启动Redis报错:Could not create server TCP listening socket 127.0.0.1:6379: bind: 操作成功完成。(已解决)
    HBase数据库基础操作
    决策树——非正常企业数目预测
    MongoDB启动报错:Unrecognized option: storage try 'mongod --help' for more information(已解决)
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9344774.html
Copyright © 2011-2022 走看看