POJ-2778

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 12726   Accepted: 4862

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

Source

推荐一个网址 :Maxtrix67

/**
    题意:给出n个字符串,问长度为m的字符串中有多少没有包含病毒
    做法:AC自动机 + 矩阵快速幂 
        Maxtrix 67 给出的定理8
        经典题目8 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
        把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。  令C=A*A,
        那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。
        类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的路径数,
        我们只需要二分求出A^k即可。
**/
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#include <map>
#define MM 10
#define mod 100000
using namespace std;
struct Matrix
{
    unsigned long long mat[140][140];
    int n;
    Matrix(){}
    Matrix(int _n)
    {
        n = _n;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                mat[i][j] = 0;
            }
        }
    }
    Matrix operator *(const Matrix &b) const
    {
        Matrix res = Matrix(n);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                res.mat[i][j] = 0;
                for(int k=0;k<n;k++)
                {
                    res.mat[i][j] += mat[i][k] * b.mat[k][j];
                }
                res.mat[i][j] %= mod;
            }
        }
        return res;
    }
};
unsigned long long quick_pow(unsigned long long a,int n)
{
    unsigned long long res = 1;
    unsigned long long tmp = a;
    while(n)
    {
        if(n&1) res *= tmp;
        tmp *= tmp;
        n >>= 1;
    }
    return res;
}
Matrix quick_pow(Matrix a,int n)
{
    Matrix res = Matrix(a.n);
    for(int i=0;i<a.n;i++)
    {
        res.mat[i][i] = 1;
    }
    Matrix tmp = a;
    while(n)
    {
        if(n&1) res =res * tmp;
        tmp = tmp * tmp;
        n >>= 1;
    }
    return res;
}
struct Tire
{
    int next[110][MM],fail[110];
    bool end[110];
    int L,root;
    map<char,int>id;
    int newnode()
    {
        for(int i=0;i<MM;i++)
        {
            next[L][i] = -1;
        }
        end[L++] = 0;
        return L-1;
    }
    void init()
    {
        L = 0;
        root = newnode();
        id['A'] = 0;
        id['T'] = 1;
        id['C'] = 2;
        id['G'] = 3;
    }
    void insert(char buf[])
    {
        int now = root;

        int len = strlen(buf);
        for(int i=0;i<len;i++)
        {
            if(next[now][id[buf[i]]] == -1)
                next[now][id[buf[i]]] = newnode();
            now = next[now][id[buf[i]]];
        }
        end[now] = true;
    }
    void build()
    {
        queue<int>que;
        int now = root;
        fail[root] = root;
        for(int i=0;i<4;i++)
        {
            if(next[now][i] == -1)
                next[now][i] = root;
            else
            {
                fail[next[now][i]] = root;
                que.push(next[now][i]);
            }
        }
        while(!que.empty())
        {
            now = que.front();
            que.pop();
            if(end[fail[now]]) end[now] = true;
            for(int i=0;i<4;i++)
            {
                if(next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else 
                {
                    fail[next[now][i]] = next[fail[now]][i];
                    que.push(next[now][i]);
                }
            }
        }
    }
    Matrix getMatrix()
    {
        Matrix res = Matrix(L+1);
        for(int i=0;i<L;i++)
        {
            for(int j=0;j<4;j++)
            {
                if(end[next[i][j]] == false && !end[i])
                    res.mat[i][next[i][j]] ++;
            }
        }
        return res;
    }
};
char buf[100];
Tire ac;
int main()
{
   // freopen("in.txt","r",stdin);
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        ac.init();
        for(int i=0;i<n;i++)
        {
            scanf("%s",buf);
            ac.insert(buf);
        }
        ac.build();
        Matrix a = ac.getMatrix();
        a = quick_pow(a,m);
        unsigned long long res = 0;
        for(int i=0;i<a.n;i++)
        {
            res += a.mat[0][i];
        }
        cout<<res%mod<<endl;
    }
    return 0;
}

 

posted on 2015-05-08 12:38  `Elaine  阅读(172)  评论(0编辑  收藏  举报

导航