zoukankan      html  css  js  c++  java
  • POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)

    http://poj.org/problem?id=2778

    题意:
    给出一些病毒字符串,只由A,T,C,G组成,现在要用着4个字符组成长度为n的字符串,且字符串中不可以包含任一病毒字符串,问共有多少种字符串。

    思路:

    回想一下离散数学中所学的邻接矩阵

    而AC自动机的状态图就是一个有向图,我们只需要根据这个有向图建立邻接矩阵即可,因为不可以包含病毒串,所以只需要判断是否是字符串结尾,如果不是就说明可以连接起来。

    注意在fail转移的时候传递字符串结尾标记。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 const int INF = 0x3f3f3f3f;
     14 const int maxn=10000+5;
     15 const int mod=100000;
     16 
     17 int n, m, num;
     18 char s[20];
     19 
     20 struct Trie
     21 {
     22     int son[10];
     23     int cnt;
     24     int fail;
     25 }t[150];
     26 
     27 
     28 struct Matrix
     29 {
     30     ll mat[200][200], n;
     31     Matrix(){}
     32     Matrix(int _n)
     33     {
     34         n=_n;
     35         for(int i=0;i<n;i++)
     36         for(int j=0;j<n;j++)
     37             mat[i][j]=0;
     38     }
     39     Matrix operator*(const Matrix& b) const
     40     {
     41         Matrix c=Matrix(n);
     42         for(int i=0;i<n;i++)
     43         {
     44             for(int j=0;j<n;j++)
     45             {
     46                 for(int k=0;k<n;k++)
     47                 {
     48                     c.mat[i][j]=(c.mat[i][j]+mat[i][k]*b.mat[k][j])%mod;
     49                 }
     50             }
     51         }
     52         return c;
     53     }
     54 };
     55 
     56 void init(int x)
     57 {
     58     t[x].fail=0;
     59     t[x].cnt=0;
     60     memset(t[x].son,0,sizeof(t[x].son));
     61 }
     62 
     63 int getch(char ch)
     64 {
     65     if(ch=='A')   return 1;
     66     if(ch=='T')   return 2;
     67     if(ch=='C')   return 3;
     68     if(ch=='G')   return 4;
     69 }
     70 
     71 void trie(char *s)
     72 {
     73     int n=strlen(s);
     74     int x=0;
     75     for(int i=0;i<n;i++)
     76     {
     77         int c=getch(s[i]);
     78         if(!t[x].son[c])
     79         {
     80             num++;
     81             init(num);
     82             t[x].son[c]=num;
     83         }
     84         x=t[x].son[c];
     85     }
     86     t[x].cnt=1;
     87 }
     88 
     89 void buildAC()
     90 {
     91     queue<int> Q;
     92     for(int i=1;i<=4;i++)  if(t[0].son[i])  Q.push(t[0].son[i]);
     93     while(!Q.empty())
     94     {
     95         int x=Q.front(); Q.pop();
     96         int fail=t[x].fail;
     97         for(int i=1;i<=4;i++)
     98         {
     99 
    100             int y=t[x].son[i];
    101             if(y)
    102             {
    103                 t[y].fail=t[fail].son[i];
    104                 t[y].cnt|=t[t[fail].son[i]].cnt;  //这儿很重要,这个标记需要传递
    105                 Q.push(y);
    106             }
    107             else t[x].son[i]=t[fail].son[i];
    108         }
    109     }
    110 }
    111 
    112 Matrix getMatrix()
    113 {
    114     Matrix c=Matrix(num+1);
    115     for(int i=0;i<=num;i++)
    116     {
    117         for(int j=1;j<=4;j++)
    118         {
    119             if(t[t[i].son[j]].cnt==0)  c.mat[i][t[i].son[j]]++;
    120         }
    121     }
    122     return c;
    123 }
    124 
    125 
    126 void q_pow(Matrix base, int n)
    127 {
    128     Matrix ans=Matrix(base.n);
    129     for(int i=0;i<ans.n;i++)   ans.mat[i][i]=1;
    130     while(n)
    131     {
    132         if(n&1)  ans=ans*base;
    133         base=base*base;
    134         n>>=1;
    135     }
    136     int res=0;
    137     for(int i=0;i<ans.n;i++)
    138         res=(res+ans.mat[0][i])%mod;
    139     printf("%d
    ",res);
    140 }
    141 
    142 int main()
    143 {
    144     //freopen("in.txt","r",stdin);
    145     while(~scanf("%d%d",&m,&n))
    146     {
    147         init(0);
    148         num=0;
    149         for(int i=1;i<=m;i++)
    150         {
    151             scanf("%s",s);
    152             trie(s);
    153         }
    154         buildAC();
    155         Matrix c=getMatrix();
    156         q_pow(c,n);
    157     }
    158     return 0;
    159 }
  • 相关阅读:
    *VC编程规范
    C++的va_start() va_end()函数应用(转)
    * C++类的分解,抽象类与纯虚函数的需要性
    *C++中的回调
    *C++中使用接口
    C++模版使用
    *获取mac地址的方法
    *数字——字符之间的转换(转)
    eclipse雕虫小技一:eclipse打开文件目录
    Hibernate升级后注解方式的对象关系映射
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7439547.html
Copyright © 2011-2022 走看看