poj2778 DNA Sequence

http://www.elijahqi.win/archives/2886
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

POJ Monthly–2006.03.26,dodo
和上午做的一题完全相同 只不过这次改成了求不会出现的个数 而且这个n这么大 然后字符串的长度这么小可以想象到用矩阵快速幂优化下dp转移即可ac 另外意识到取模真的很慢..

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 100000
#define N 110
#define ll long long 
using namespace std;
int cnt=1,n,m,trans[N][4],c[500],fail[N];char s[11];bool end[N]; 
inline void insert1(char s[]){
    int len=strlen(s+1);int p=1;
    for (int i=1,nxt;i<=len;++i){
        if (!trans[p][c[s[i]]]) trans[p][c[s[i]]]=nxt=++cnt;
        else nxt=trans[p][c[s[i]]];p=nxt;
    }end[p]=1;
}
inline void buildAC(){
    queue<int> q;q.push(1);for (int i=0;i<4;++i) trans[0][i]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        for (int i=0;i<4;++i){
            int &y=trans[x][i];
            if (y) fail[y]=trans[fail[x]][i],q.push(y);
            else {y=trans[fail[x]][i];continue;}end[y]|=end[fail[y]];
        }
    }
}
struct matrix{ll f[110][110];}ans,base;
inline matrix multiply(const matrix &a,const matrix &b){
    matrix c;memset(c.f,0,sizeof(c.f));
    for (int i=1;i<=cnt;++i)
        for (int k=1;k<=cnt;++k)
            for (int j=1;j<=cnt;++j)
                c.f[i][j]+=a.f[i][k]*b.f[k][j];
    for (int i=1;i<=cnt;++i)
        for (int j=1;j<=cnt;++j) c.f[i][j]%=mod;
    return c;
}
int main(){
    freopen("poj2778.in","r",stdin);
    scanf("%d%d",&m,&n);c['A']=0;c['T']=1;c['C']=2;c['G']=3;
    for (int i=1;i<=m;++i) scanf("%s",s+1),insert1(s);buildAC();
    for (int i=1;i<=cnt;++i){
        if (end[i])continue;
        for (int j=0;j<4;++j){
            if(end[trans[i][j]]) continue;
            ++base.f[i][trans[i][j]];
        }
    }for (int i=1;i<=cnt;++i) ans.f[i][i]=1;int ans1=0;
    for (int t=n;t;t>>=1,base=multiply(base,base)) if (t&1) ans=multiply(ans,base);
    for (int i=1;i<=cnt;++i) ans1=ans1+ans.f[1][i]>=mod?ans1+ans.f[1][i]-mod:ans1+ans.f[1][i];
    printf("%d\n",ans1);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值