POJ 2778 DNA Sequence (AC自动机+矩阵加速,4级)

E - DNA Sequence
Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Appoint description:

Description

It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For example, if a animal's DNA sequence contains segment ATC then it may mean that the animal may have a genetic disease. Until now scientists have found several those segments, the problem is how many kinds of DNA sequences of a species don't contain those segments.

Suppose that DNA sequences of a species is a sequence that consist of A, C, T and G,and the length of sequences is a given integer n.

Input

First line contains two integer m (0 <= m <= 10), n (1 <= n <=2000000000). Here, m is the number of genetic disease segment, and n is the length of sequences.

Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.

Output

An integer, the number of DNA sequences, mod 100000.

Sample Input

4 3
AT
AC
AG
AA

Sample Output

36

思路:直接用AC自动机预处理出失败指针转移态,然后根据失败指针的转移态建立递推矩阵,外加个快速幂轻松搞定。
     mod很占时间能不mod尽量少mod

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define clr(f,z) memset(f,z,sizeof(f))
#define LL unsigned long long
using namespace std;
const int msize=510;
const int sig=4;
const int mod=100000;
class Matrix
{
public:
  LL f[140][140];
  int n;
  Matrix();
  Matrix(int x)
  {
    n=x;
    FOR(i,0,x-1)FOR(j,0,x-1)f[i][j]=0;
  }
  Matrix operator*(const Matrix&b)const
  {
    Matrix c=Matrix(n);
    FOR(i,0,n-1)FOR(j,0,n-1){FOR(k,0,n-1)
      c.f[i][j]+=f[i][k]*b.f[k][j];
     c.f[i][j]%=mod;
    }
    return c;
  }
};
class AC_Machine
{
  public:int f[msize],ch[msize][sig],sz;
         bool val[msize];
  void clear()
  {
    sz=1;clr(ch[0],0);val[0]=0;
  }
  int idx(char x)
  {
    if(x=='A')return 0;
    if(x=='G')return 1;
    if(x=='C')return 2;
    if(x=='T')return 3;
  }
  void insert(char*s)
  {
    int u=0,v,c;
    for(int i=0;s[i];++i)
    {
      c=idx(s[i]);
      if(!ch[u][c])
      {
        clr(ch[sz],0);val[sz]=0;
        ch[u][c]=sz++;
      }
      u=ch[u][c];
    }
    val[u]=1;
  }
  void getFail()
  {
    int u=0,v,r;
    queue<int>Q;
    FOR(c,0,sig-1)
    {
      u=ch[0][c];
      if(u)
      {
        f[u]=0;Q.push(u);
      }
    }
    while(!Q.empty())
    {
      r=Q.front();Q.pop();
      val[r]|=val[ f[r] ];
      FOR(c,0,sig-1)
      {
        u=ch[r][c];
        if(!u)
        {
          ch[r][c]=ch[ f[r] ][c];continue;
        }
        v=f[r];Q.push(u);
        while(v&&!ch[v][c])v=f[v];
        f[u]=ch[v][c];
      }
    }
  }
  Matrix getMatrix()
  {
    Matrix ret=Matrix(sz);
    FOR(i,0,sz-1)
    FOR(j,0,3)
    if(!val[ch[i][j]])
    {
      ret.f[i][ ch[i][j] ]++;
    }
    return ret;
  }
};
Matrix M_pow(Matrix a,int m)
{
  Matrix ret=Matrix(a.n);
  FOR(i,0,a.n-1)ret.f[i][i]=1;
  while(m)
  {
    if(m&1)ret=ret*a;
    a=a*a;
    m>>=1;
  }
  return ret;
}
AC_Machine ac;
char s[55];
int n,m;
int main()
{
  while(~scanf("%d%d",&n,&m))
  {
    ac.clear();
    FOR(i,1,n)
    {
      scanf("%s",s);
      ac.insert(s);
    }
    ac.getFail();
    Matrix ret=ac.getMatrix();
    ret=M_pow(ret,m);
    LL ans=0;
    FOR(i,0,ac.sz-1)
    ans+=ret.f[0][i];
    ans%=mod;
    printf("%lld\n",ans);
  }
}


posted @ 2013-08-27 19:03  剑不飞  阅读(204)  评论(0编辑  收藏  举报