zoukankan      html  css  js  c++  java
  • Hdu 3962 Microgene (AC自己主动机+矩阵)

    标题效果:

    构造一个字符串,使得有两个和两个以上的目标串。长短L这一系列有多少串都。


    IDEAS:

    只有全款减有1一些字符串,没有目标就是答案。

    假定数据是非常小的,够用dp解。dp[i][j][k] 表示长度为i,走到自己主动机的j。有k个目标串的数量。

    转移便是。

    if(j->next[d] ->isword) dp[i+1][j->next][1] += dp[i][j][0].

    else dp[i+1][j->next][0]+=dp[i][j][0],dp[i+1][j->next][1] += dp[i][j][1]...

    如今长度达到百万。

    所以用矩阵优化。

    设自己主动机的节点数量为idx,那么就开一个(2*idx。2*idx)的矩阵。

    假设i<idx j<idx 表示 開始在i的时候没有目标串,走到j也没有。

    假设i<idx j>idx 表示 開始在i的时候没有目标串。走到j有了一个。

    后面同理。

    。。

    那么构造这个矩阵便是依照上面的dp方程类似构造。

    if(j->next[d]->isword)matrix [i][j->next->index+idx]++; 開始的时候没有,走过来加一个

    else matrix [i][j]++,matrix [i+idx][j+idx] 開始的时候没有,走到j也没有  和  開始的时候有一个,走到j还是一个。

    矩阵的构造是难= =


    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define N 75
    using namespace std;
    
    const int mod = 10007;
    const char tab = 'a';
    const int max_next = 4;
    int rev[256];
    struct trie
    {
        struct trie *fail;
        struct trie *next[max_next];
        int isword;
        int index;
    };
    struct AC
    {
        trie *que[100005],*root,ac[100005];
        int head,tail;
        int idx;
        trie *New()
        {
            trie *temp=&ac[idx];
            for(int i=0;i<max_next;i++)temp->next[i]=NULL;
            temp->fail=NULL;
            temp->isword=0;
            temp->index=idx++;
            return temp;
        }
        void init()
        {
            idx=0;
            root=New();
        }
        void Insert(trie *root,char *word,int len){
            trie *t=root;
            for(int i=0;i<len;i++){
                if(t->next[rev[word[i]]]==NULL)
                    t->next[rev[word[i]]]=New();
                t=t->next[rev[word[i]]];
            }
            t->isword++;
        }
        void acbuild(trie *root){
            int head=0,tail=0;
            que[tail++]=root;
            root->fail=NULL;
            while(head<tail){
                trie *temp=que[head++],*p;
                for(int i=0;i<max_next;i++){
                     if(temp->next[i]){
                        if(temp==root)temp->next[i]->fail=root;
                        else {
                            p=temp->fail;
                            while(p!=NULL){
                                if(p->next[i]){
                                    temp->next[i]->fail=p->next[i];
                                    break;
                                }
                                p=p->fail;
                            }
                            if(p==NULL)temp->next[i]->fail=root;
                        }
                        if(temp->next[i]->fail->isword)temp->next[i]->isword++;
                        que[tail++]=temp->next[i];
                     }
                     else if(temp==root)temp->next[i]=root;
                     else temp->next[i]=temp->fail->next[i];
                }
            }
        }
        void tra()
        {
            for(int i=0;i<idx;i++)
            {
                if(ac[i].fail!=NULL)printf("fail = %d ",ac[i].fail->index);
                for(int k=0;k<max_next;k++)
                    printf("%d ",ac[i].next[k]->index);
                puts("");
            }
        }
    }sa;
    
    struct matrix
    {
        int r,c;
        int data[N][N];
        matrix(){}
        matrix(int _r,int _c):r(_r),c(_c){memset(data,0,sizeof data);}
        friend matrix operator * (const matrix A,const matrix B)
        {
            matrix res;
            res.r=A.r;res.c=B.c;
            memset(res.data,0,sizeof res.data);
            for(int i=0;i<A.r;i++)
            {
                for(int j=0;j<B.c;j++)
                {
                    for(int k=0;k<A.c;k++)
                    {
                        if(A.data[i][k] && B.data[k][j]){
                            res.data[i][j]+=A.data[i][k]*B.data[k][j];
                            res.data[i][j]%=mod;
                        }
                    }
                }
            }
            return res;
        }
        friend matrix operator + (const matrix A,const matrix B)
        {
            matrix res;
            res.r=A.r;res.c=A.c;
            memset(res.data,0,sizeof res.data);
            for(int i=0;i<A.r;i++)
            {
                for(int j=0;j<A.c;j++)
                {
                    res.data[i][j]=A.data[i][j]+B.data[i][j];
                    res.data[i][j]%=mod;
                }
            }
            return res;
        }
        friend matrix operator - (const matrix A,const matrix B)
        {
            matrix res;
            res.r=A.r;res.c=A.c;
            memset(res.data,0,sizeof res.data);
            for(int i=0;i<A.r;i++)
            {
                for(int j=0;j<A.c;j++)
                {
                    res.data[i][j]=A.data[i][j]-B.data[i][j];
                    res.data[i][j]=(res.data[i][j]%mod+mod)%mod;
                }
            }
            return res;
        }
        friend matrix operator ^ (matrix A,int n)
        {
            matrix res;
            res.r=A.r;res.c=A.c;
            memset(res.data,0,sizeof res.data);
            for(int i=0;i<A.r;i++)res.data[i][i]=1;
    
            while(n)
            {
                if(n&1)res=res*A;
                A=A*A;
                n>>=1;
            }
            return res;
        }
        void print()
        {
            for(int i=0;i<r;i++)
            {
                for(int j=0;j<c;j++)
                    printf("%d ",data[i][j]);
                puts("");
            }
        }
    }E,zero;
    
    char word[30];
    
    int main()
    {
        rev['A']=0;
        rev['C']=1;
        rev['G']=2;
        rev['T']=3;
        int n,L;
        while(scanf("%d%d",&n,&L)!=EOF)
        {
            sa.init();
            for(int i=1;i<=n;i++)
            {
                scanf("%s",word);
                sa.Insert(sa.root,word,strlen(word));
            }
            sa.acbuild(sa.root);
            E=matrix(sa.idx*2,sa.idx*2);
    
            for(int i=0;i<sa.idx*2;i++)E.data[i][i]=1;
    
            matrix origin=matrix(sa.idx*2,sa.idx*2);
    
            for(int i=0;i<sa.idx;i++)
            {
                for(int j=0;j<4;j++)
                {
                    int temp=sa.ac[i].next[j]->index;
                    if(sa.ac[i].next[j]->isword)
                        origin.data[i][temp+sa.idx]++;
                    else
                        origin.data[i][temp]++,origin.data[i+sa.idx][temp+sa.idx]++;
                }
            }
            origin.print();
    
            origin=origin^L;
    
            int ans=1;
            int x=4;
            int t=L;
            while(t)
            {
                if(t&1)ans=(ans*x)%mod;
                x=(x*x)%mod;
                t>>=1;
            }
            for(int i=0;i<2*sa.idx;i++)
            {
                ans-=origin.data[0][i];
                ans=(ans+mod)%mod;
            }
    
            printf("%d
    ",ans);
        }
        return 0;
    }
    



    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    第十一周作业
    第十周作业
    第九周编程
    第十二周作业
    第十一周作业
    第十周作业
    第八周作业
    第七周作业
    第五周作业
    2019春季学期第四周作业
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4799978.html
Copyright © 2011-2022 走看看