POJ 3691 DNA Sequence (AC自动机 + 矩阵 有bug,待修改)

DNA Sequence
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9889   Accepted: 3712

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

 
 
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N=110;
const int mod=100000;

struct Trie{
    int ok;
    int fail;
    int next[4];
    void Init(){
        ok=0;
        fail=-1;
        memset(next,-1,sizeof(next));
    }
}a[N];

char wrd[30];
char str[N];
int n,m,cnt,q[N];

int find(char ch){
    switch(ch){
        case 'A':return 0;
        case 'C':return 1;
        case 'T':return 2;
        case 'G':return 3;
    }
    return 0;
}

void InsertTrie(char *str){
    int p=0;
    for(int i=0;str[i]!='';i++){
        int id=find(str[i]);
        if(a[p].ok)
            break;
        if(a[p].next[id]==-1){
            a[p].next[id]=cnt++;
            a[cnt-1].Init();
        }
        p=a[p].next[id];
    }
    a[p].ok++;
}

void AC_automation(){
    int head=0,tail=0;
    q[tail++]=0;
    int cur=0,tmp;
    while(head<tail){
        cur=q[head++];
        for(int i=0;i<4;i++){
            tmp=a[cur].next[i];
            if(tmp!=-1){
                if(cur==0)
                    a[tmp].fail=0;
                else{
                    a[tmp].fail=a[a[cur].fail].next[i];
                    if(a[a[tmp].fail].ok)
                        a[tmp].ok++;
                }
                q[tail++]=a[cur].next[i];
            }else{
                if(cur==0)
                    a[cur].next[i]=0;
                else
                    a[cur].next[i]=a[a[cur].fail].next[i];
            }
        }
    }
}

struct Matrix{
    long long m[110][110];
};

Matrix init,unit;

void Init(){
    memset(init.m,0,sizeof(init.m));
    for(int i=0;i<cnt;i++)
        if(!a[i].ok)
            for(int j=0;j<4;j++){
                if(a[a[i].next[j]].ok==0)
                    init.m[i][a[i].next[j]]++;
            }
                //if(a[*a[i].next[j]].ok==0)
                    //init.m[i][*a[i].next[j]]++;
    for(int i=0;i<cnt;i++)
        for(int j=0;j<cnt;j++)
            unit.m[i][j]=(i==j)?1:0;
}

Matrix Mul(Matrix a,Matrix b){
    Matrix c;
    for(int i=0;i<cnt;i++)
        for(int j=0;j<cnt;j++){
            c.m[i][j]=0;
            for(int k=0;k<cnt;k++)
                c.m[i][j]=(a.m[i][k]*b.m[k][j])%mod;
            c.m[i][j]%=mod;
        }
    return c;
}

Matrix Pow(Matrix a,Matrix b,int k){
    while(k){
        if(k&1){
            b=Mul(a,b);
        }
        a=Mul(a,a);
        k>>=1;
    }
    return b;
}

int main(){

    freopen("input.txt","r",stdin);

    while(~scanf("%d%d",&n,&m)){
        cnt=1;
        a[0].Init();
        for(int i=0;i<n;i++){
            scanf("%s",wrd);
            InsertTrie(wrd);
        }
        AC_automation();
        Init();
        Matrix res=Pow(init,unit,m);
        long long ans=0;
        for(int i=0;i<cnt;i++)
            if(a[i].ok==0)
                ans=(ans+res.m[0][i])%mod;
        cout<<ans<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jackge/p/3147573.html