以下内容均为转载,,只有代码是自己写的=-=

http://blog.csdn.net/morgan_xww/article/details/7834801   转载地址 博主写的很好

---------------------------------------------------------------------------------------我是分割线

DNA Sequence
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 16585   Accepted: 6408

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
•题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。(仅含A,T,C,G四个字符)
•样例m=4,n=3,{“AA”,”AT”,”AC”,”AG”}
•答案为36,表示有36种长度为3的序列可以不包含疾病
 
这个和矩阵有什么关系呢???
•上图是例子{“ACG”,”C”},构建trie图后如图所示,从每个结点出发都有4条边(A,T,C,G)
•从状态0出发走一步有4种走法:
  –走A到状态1(安全);
  –走C到状态4(危险);
  –走T到状态0(安全);
  –走G到状态0(安全);
•所以当n=1时,答案就是3
•当n=2时,就是从状态0出发走2步,就形成一个长度为2的字符串,只要路径上没有经过危险结点,有几种走法,那么答案就是几种。依此类推走n步就形成长度为n的字符串。
•建立trie图的邻接矩阵M:

2 1 0 0 1

2 1 1 0 0

1 1 0 1 1

2 1 0 0 1

2 1 0 0 1

M[i,j]表示从结点i到j只走一步有几种走法。

那么M的n次幂就表示从结点i到j走n步有几种走法。

注意:危险结点要去掉,也就是去掉危险结点的行和列。结点3和4是单词结尾所以危险,结点2的fail指针指向4,当匹配”AC”时也就匹配了”C”,所以2也是危险的。

矩阵变成M:

2 1

2 1

计算M[][]的n次幂,然后 Σ(M[0,i]) mod 100000 就是答案。

由于n很大,可以使用二分来计算矩阵的幂

#include<cstdio>
#include<map>
#include<queue>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;
const int N=101;
const int mod=1e5;
struct Mat
{
    ll mat[N][N];
    Mat operator *(const Mat &B)const
    {
        Mat C;
        memset(C.mat,0,sizeof(C.mat));
        for(int k=0; k<N; ++k)
        {
            for(int i=0; i<N; ++i)
            {
                if(mat[i][k]==0) continue;
                for(int j=0; j<N; ++j)
                {
                    if(B.mat[k][j]==0) continue;
                    C.mat[i][j]=(C.mat[i][j]+mat[i][k]*B.mat[k][j])%mod;
                }
            }
        }
        return C;
    }
    int operator ^(int &k)
    {
        Mat C;
        memset(C.mat,0,sizeof(C.mat));
        for(int i=0; i<N; ++i)
            C.mat[i][i]=1;
        while(k)
        {
            if(k&1)
            {
                C=C*(*this);
                --k;
            }
            k>>=1;
            (*this)=(*this)*(*this);
        }
        int cnt=0;
        for(int i=0; i<N; ++i)
            cnt=(cnt+C.mat[0][i])%mod;
        return cnt;
    }
};
struct AC{
     int ch[58][4],fail[58],val[58],sz,rt,id[128];
     void init(){
        sz=rt=0;
        memset(ch[rt],-1,sizeof(ch[rt]));
        id['A']=0,id['G']=1,id['T']=2,id['C']=3;
     }
     void insert(char *str){
        int u=rt,len=strlen(str);
        for(int i=0;i<len;++i){
            int op=id[str[i]];
            if(ch[u][op]==-1) {
                ++sz;
                memset(ch[sz],-1,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][op]=sz;
            }
            u=ch[u][op];
        }
        val[u]=1;
     }
     void build(){
        queue<int>Q;
        int u=rt;
        for(int i=0;i<4;++i){
            if(ch[u][i]==-1) ch[u][i]=rt;
            else {
                fail[ch[u][i]]=rt;
                Q.push(ch[u][i]);
            }
        }
        while(!Q.empty()){
            u=Q.front();
            Q.pop();
            val[u]|=val[fail[u]];
            for(int i=0;i<4;++i){
                if(ch[u][i]==-1) ch[u][i]=ch[fail[u]][i];
                else {
                    fail[ch[u][i]]=ch[fail[u]][i];
                    Q.push(ch[u][i]);
                }
            }
        }
     }
     void work(int n){
        Mat A;
        memset(A.mat,0,sizeof(A.mat));
        for(int i=0;i<=sz;++i)
            for(int j=0;j<4;++j)
            if(!val[ch[i][j]]) ++A.mat[i][ch[i][j]];
        printf("%d\n",A^n);
     }
}ac;
char s[55];
int main(){
    int m,n;
    while(scanf("%d%d",&m,&n)!=EOF){
        ac.init();
        while(m--){
            scanf("%s",s);
            ac.insert(s);
        }
        ac.build();
        ac.work(n);
    }
}

poj2778 AC自动机的更多相关文章

  1. poj2778 ac自动机+矩阵快速幂

    给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://we ...

  2. 【POJ2778】DNA Sequence(AC自动机,DP)

    题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATC ...

  3. 【POJ2778】AC自动机+矩阵乘法

    DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...

  4. poj2778(AC 自动机)

    poj2778 题意 构造只包含 \(A, T, C, G\) 的字符串,且满足不出现指定的一些字符串,问长度为 \(n\) 的字符串有多少种 ? 分析 AC 自动机 + 矩阵快速幂的神题 ,知识点很 ...

  5. POJ2778 DNA Sequence(AC自动机 矩阵)

    先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数. #include<cstdio& ...

  6. POJ2778 DNA Sequence(AC自动机+矩阵快速幂)

    题目给m个病毒串,问不包含病毒串的长度n的DNA片段有几个. 感觉这题好神,看了好久的题解. 所有病毒串构造一个AC自动机,这个AC自动机可以看作一张有向图,图上的每个顶点就是Trie树上的结点,每个 ...

  7. poj2778(AC自动机+矩阵快速幂)

    题意:给你n个字符串,问你长度为m的字符串且字符串中不含有那n个子串的字符串的数量 解题思路:这道题一开始就不太懂,还以为是组合数学的题目,后面看了别人的博客,才知道这是属于AC自动机的另一种用法,是 ...

  8. 【POJ2778】DNA Sequence 【AC自动机,dp,矩阵快速幂】

    题意 题目给出m(m<=10)个仅仅由A,T,C,G组成的单词(单词长度不超过10),然后给出一个整数n(n<=2000000000),问你用这四个字母组成一个长度为n的长文本,有多少种组 ...

  9. poj2778 DNA Sequence【AC自动机】【矩阵快速幂】

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19991   Accepted: 7603 Des ...

随机推荐

  1. VS2013 配置全局 VC++目录

    原文链接:https://blog.csdn.net/humanking7/article/details/80391914 也许是我VS2013安装的有问题,每次编译程序都要去 项目属性页-> ...

  2. div/dom元素拖拽缩放插件,纯js实现拖拽缩放,不依赖jQuery~

    产品需求,需要用到对div(dom)进行拖拽缩放操作,看到有好多插件,要么依赖jQuery,要么文件太大. 封装了一个插件,不压缩状态下5KB. html <!DOCTYPE html> ...

  3. zabbix3.x.x升级教程

    1:停掉正在运行的zabbix服务,确保没有新数据写入数据库. /etc/init.d/zabbix_server stop 2:备份原zabbix的数据库数据,以及相关文件. mysqldump - ...

  4. 使用mvp+rxjava+retrofit加载数据

    将mvp和rxjava和retrofit简单整合的列子,让activity的代码不再那么臃肿,只负责显示数据. 关于mvp的介绍可以看这里, 关于Rxjava的介绍可以看这里; 关于retrofit的 ...

  5. Merge_Sort

    public class Merge_Sort { public static void merge(int a[],int n){ int source; //合并之前数组的大小 int targe ...

  6. 题解 P2261【[CQOI2007]余数求和】

    P2261[[CQOI2007]余数求和] 蒟蒻终于不看题解写出了一个很水的蓝题,然而题解不能交了 虽然还看了一下自己之前的博客 题目要求: \[\sum_{i=1}^{n}{k \bmod i} \ ...

  7. spring bootweb综合开发的整理

    1.json接口开发 当前开发中微服务的概念日渐深入人心,所以json数据交互可以带来的便利也不言而喻.在springboot中json数据的返回方式比较简单,只需要用@RestController注 ...

  8. POJ3734(矩阵快速幂)

    \(假设现在到第i个积木\) \(红绿恰都是偶数a种方案,恰都是奇数为b种方案,一奇一偶为c种方案\) \(由此考虑i+1个积木的情况\) Ⅰ.一奇一偶的方案 \(如果第i层恰是奇数的情况,那么本次只 ...

  9. Mysql常用sql语句(九)- like 模糊查询

    测试必备的Mysql常用sql语句,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1683347.html 前言 ...

  10. uCOS2014.1.8

    目前uCOS中已经接触到的全局变量: OSTCBCur OSIntNesting OSPrioHighRdy    最高优先级任务 任哲编著<嵌入式实时操作系统uC/OS-II原理及应用> ...