zoukankan      html  css  js  c++  java
  • POJ 2778(自动机+矩阵幂乘(字符串果然是个坑爹玩应!))

    参考:http://hi.baidu.com/ccsu_010/item/7847a3c17f6fe2bc0d0a7b89

    关键是状态转移,矩阵就是解决状态转移的!(比较难)

    数据量:1 <= n <=2000000000(明显快速算法!)

    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

    //#pragma comment(linker, "/STACK:102400000")
    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<list>
    #include<queue>
    #include<stack>
    #include<vector>
    #define tree int o,int l,int r
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define lo o<<1
    #define ro o<<1|1
    #define pb push_back
    #define mp make_pair
    #define ULL unsigned long long
    #define LL long long
    #define inf 0x7fffffff
    #define eps 1e-7
    #define N 109
    #define M 4
    #define mod 100000
    using namespace std;
    int m,n,T,t,x,y,u;
    int ch[N][4];
    int v[N];
    int f[N],last[N],num;
    LL ma[N][N],temp[N][N];
    void clear()//Trie树初始化
    {
        memset(ma,0,sizeof(ma));
        num=1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(v,0,sizeof(v));
        memset(last,0,sizeof(last));
    }
    int idx(char c)
    {
        switch(c)
        {
            case 'A':return 0;
            case 'C':return 1;
            case 'G':return 2;
            case 'T':return 3;
        }
        return 0;
    }
    void insert(char str[],int value)//建Trie树
    {
        int len=strlen(str);
        int u=0;
        for (int i=0; i<len; ++i )
        {
            int c=idx(str[i]);
            if(!ch[u][c])//保存的是结点坐标
            {
                memset(ch[num],0,sizeof(ch[num]));
                ch[u][c]=num++;//
            }
            u=ch[u][c];
        }
        v[u]=value;
    }
    void getac()
    {
        queue<int> q;//保存的节点下标
        f[0]=0;
        for (int c=0; c<M; ++c )
        {
            int u=ch[0][c];
            if(u)//不需要优化的else
            {
                q.push(u);
                f[u]=0;
                last[u]=v[u];//WA,可能有长度为1的串
            }
        }
        while(!q.empty())
        {
            int r=q.front();
            q.pop();
            for (int c=0; c<M; ++c )
            {
                int u=ch[r][c];
                if(u)
                {
                    q.push(u);
                    int s=f[r];
                    f[u]=ch[s][c];
                    last[u]=(v[u]||last[f[u]]);//
                }
                else //重要优化
                    ch[r][c]=ch[f[r]][c];
            }
        }
    }
    char str[20];
    void build()//构造矩阵!!!
    {
        for(int i=0;i<num;i++)
        {
            for(int j=0;j<4;j++)
            {
                int u=ch[i][j];
                if(last[u]==0)
                ma[i][u]++;
            }
        }
    }
    void malti(LL a[][N],LL b[][N],int n)
    {
        LL c[N][N]={0};
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        for(int k=0;k<n;k++)
        {
            c[i][j]+=a[i][k]*b[k][j];
            c[i][j]%=mod;
        }
        memcpy(a,c,sizeof(c));
    }
    void mat(LL ma[][N],int n,int num)
    {
        memset(temp,0,sizeof(temp));
        for(int i=0;i<num;i++)
        temp[i][i]=1;
        while(n)
        {
            if(n&1)
            {
                malti(temp,ma,num);
            }
            malti(ma,ma,num);
            n>>=1;
        }
        memcpy(ma,temp,sizeof(temp));
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
        int ncase=0;
    //    scanf("%d",&T);
    //    while(T--)
        while(scanf("%d%d%*c",&m,&n)==2)
        {
            clear();
            while(m--)
            {
                scanf("%s",str);
                insert(str,1);
            }
            getac();
            build();
    //        print2(ma,num,num);
            mat(ma,n,num);
            int ans=0;
            for(int i=0;i<num;i++)
            {
                ans+=ma[0][i];
                ans%=mod;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    剑指OFFER----面试题54. 二叉搜索树的第k大节点
    剑指OFFER----面试题53
    剑指OFFER----面试题53
    DevExpress ASP.NET Core v19.1版本亮点:Visual Studio集成
    Kendo UI for jQuery使用教程:初始化jQuery插件
    代码自动补全插件CodeMix全新发布CI 2019.7.15|改进CSS颜色辅助
    MyEclipse使用教程:使用工作集组织工作区
    DevExpress ASP.NET Core v19.1版本亮点:Pivot Grid控件等
    Kendo UI for jQuery使用教程:小部件DOM元素结构
    MyEclipse使用教程——使用DevStyle Icon Designer(二)
  • 原文地址:https://www.cnblogs.com/sbaof/p/3373588.html
Copyright © 2011-2022 走看看