poj 2778 DNA Sequence ac自动机+矩阵快速幂

来源:互联网 发布:北京电脑数据恢复公司 编辑:程序博客网 时间:2024/06/03 17:57

题意:

给你m个病毒串问长度为n的由(A,C,T,G)组成的字符串集合中不包含任意一个m中的串有多少个

分析 :

因为m<=10 m的长度也小于10 所以我们可以预处理出加一个字母后的情况(假设前x-1个字母已经满足条件那么第x个字母选什么是合法的就要看选的字母和前面组合是否是病毒串)。状态转移需要构建ac自动机获得。

///注意矩阵快速幂的时候要先加完在取mod不然会T

ACcode:

#include <iostream>#include <cstring>#include <cstdio>#include <queue>#define maxn 2000000002#define mod 100000#define ll long long#define tot 105using namespace std;char s[15];int m;ll N;struct Aho{    struct state{        int next[4];        int fail,cnt;    }s[tot];    int size;    queue<int> q;    struct Matrix{        ll mat[tot][tot];    };    Matrix mul(Matrix a,Matrix b){        Matrix ret;        for(int i=0;i<size;++i)            for(int j=0;j<size;++j){                ret.mat[i][j]=0;                for(int k=0;k<size;++k)                    ret.mat[i][j]=(ret.mat[i][j]+a.mat[i][k]*b.mat[k][j]);                ret.mat[i][j]%=mod;            }        return ret;    }    Matrix pow(Matrix a,ll n){        Matrix ret;        memset(ret.mat,0,sizeof(ret.mat));        for(int i=0;i<size;++i)ret.mat[i][i]=1;            while(n){                if(n&1)ret=mul(ret,a);                a=mul(a,a);            n>>=1;        }        return ret;    }    void init(){        while(q.size())q.pop();        for(int i=0;i<tot;++i){            memset(s[i].next,-1,sizeof(s[i].next));            s[i].fail=s[i].cnt=0;        }        size=1;    }    int get_it(char c){        if(c=='A')return 0;        if(c=='T')return 1;        if(c=='C')return 2;        if(c=='G')return 3;    }    void insert(char *str){        int n=strlen(str);        int now=0;        for(int i=0;i<n;++i){            int id=get_it(str[i]);            if(s[now].next[id]==-1)                s[now].next[id]=size++;            now=s[now].next[id];        }        s[now].cnt=1;    }    ll build(){        s[0].fail=0;        for(int i=0;i<4;++i)            if(s[0].next[i]==-1)                s[0].next[i]=0;            else {                s[s[0].next[i]].fail=0;                q.push(s[0].next[i]);            }        while(q.size()){            int u=q.front();            q.pop();            if(s[s[u].fail].cnt)s[u].cnt=1;            for(int i=0;i<4;++i)                if(s[u].next[i]==-1)                    s[u].next[i]=s[s[u].fail].next[i];            else{                s[s[u].next[i]].fail=s[s[u].fail].next[i];                q.push(s[u].next[i]);            }        }        Matrix tmp;        memset(tmp.mat,0,sizeof(tmp.mat));        for(int i=0;i<size;++i){            if(s[i].cnt)continue;            for(int j=0;j<4;++j)                if(!s[s[i].next[j]].cnt)                    tmp.mat[i][s[i].next[j]]++;        }        tmp=pow(tmp,N);        ll ans=0;        for(int i=0;i<size;++i)            ans=(ans+tmp.mat[0][i])%mod;        return ans;    }}aho;int main(){    while(scanf("%d%I64d",&m,&N)!=EOF){        aho.init();        for(int i=0;i<m;++i){            scanf("%s",s);            aho.insert(s);        }        printf("%I64d\n",aho.build());    }    return 0;}


0 0