poj2778 DNA Sequence AC自动机+矩阵乘法

DNA Sequence
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 15900 Accepted: 6137
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

题意:给你一些串,让你求有多少个长度为m的串不包含这些串。
一开始我想的容斥。。把不合法方案剪掉,但是发现不合法方案数非常难计算,因为子串出现的位置不固定,根本没地方下手。。然后就dp喽,但是这么大,用矩阵乘法优化了一下,结果半天RE,不知道哪里错了,看了看题解和我一样啊,一看代码发现怎么人家的getfail好像不太一样?一脸懵逼。结果发现都差不多啊,怎么会有问题呢。。
最后发现我手抖把加进队列的达成了fail节点。。mdzz。。

顺便熟悉一下结构体,毕竟以后肯定很有用。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1005;
typedef long long ll;
const int mo=1e5;
int a[N][10],val[N],fail[N],q[N],ans;
int tot=0,n;
char s[N];
ll m;
struct Matrix
{
    ll ret[105][105];
    Matrix(){memset(ret,0,sizeof(ret));}
    void ini()
    {
        fo(i,0,tot)ret[i][i]=1;
    }
}g;
Matrix operator *(Matrix a,Matrix b)
{
    Matrix c;
    fo(k,0,tot)
    fo(i,0,tot)if (a.ret[i][k])
    fo(j,0,tot)if (b.ret[k][j])
        c.ret[i][j]=(c.ret[i][j]+a.ret[i][k]*b.ret[k][j]%mo)%mo;
    return c;
}
Matrix operator ^(Matrix a,int b)
{
    Matrix ans;ans.ini();
    for(;b;b>>=1,a=a*a)
        if (b&1)ans=ans*a;
    return ans;
}
inline void ins()
{
    int x=0,len=strlen(s);
    fo(i,0,len-1)
    {
        int c;
        if (s[i]=='A')c=1;
        else if (s[i]=='T')c=2;
        else if (s[i]=='C')c=3;
        else if (s[i]=='G')c=4;
        c--;
        if(!a[x][c])a[x][c]=++tot;
        x=a[x][c];
    }
    val[x]=1;
}
inline void getfail()
{
    int t=0,w=0;
    fo(i,0,3)if (a[0][i])q[w++]=a[0][i];
    while(t<w)
    {
        int x=q[t++];
        fo(i,0,3)
        if (a[x][i])
        {
            int k=fail[x];
            while (k&&!a[k][i])k=fail[k];
            k=a[k][i];
            fail[a[x][i]]=k;
            if (val[k])val[a[x][i]]=1;
            q[w++]=a[x][i];
        }
        else a[x][i]=a[fail[x]][i];
    }
}
inline void build()
{
    fo(i,0,tot)if (!val[i])
        fo(k,0,3)if (!val[a[i][k]])
        g.ret[i][a[i][k]]++;
}
int main()
{
    scanf("%d%lld",&n,&m);
    fo(i,1,n)
    {
        scanf("%s",s);
        ins();
    }
    getfail();
    build();
    g=g^m;
    ll ans=0;
    fo(i,0,tot)ans=(ans+g.ret[0][i])%mo;
    printf("%lld",ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值