博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DNA Sequence POJ - 2778
阅读量:6102 次
发布时间:2019-06-20

本文共 3025 字,大约阅读时间需要 10 分钟。

  

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 3ATACAGAA

Sample Output

36 题意:首先输入的是n和m,分别代表接下来会给你n个病毒串,问你长度为m的不包含病毒的串有多少种 思路:上次写这道题还是半年前及爱情在家写的,当时尚神指导,轻松AC,然而今天奉老大之命前来复习,读题之后发现,蒙蒙哒~~      首先我们在纸上手动模拟一下或许会对这个题的理解更深刻,我们构建一个AC自动机树,在简单题中,我们已经熟练掌握了建树以及构建fail指针的方式,这道题即是使用到了这个树的一些实际意义。      我们在构建fail指针的时候,加了一部分代码即是
if(en[fail[now]] != 0)            {                en[now] = 1;            }

什么意思呢,我们先来看fail指针的意义,树上每个结点代表一个子串,一个结点的fail指针指向另一个结点,代表的是这个后者是前者的一个后缀,这个在之前应该就是了解的。

然后如果en[fail[now]]!=0 即代表该节点的后缀包含一个病毒串,自然,这个串也是不可以使用的,于是这个点代表的串也是一个病毒串。病毒串是不可以出现的。

接下来我们来讨论为什么AC树是一个状态转移树,每个结点代表的是一个子串,那么从一个串经过next数组到达另一个串,他的意义就是经过一步可以由状态i转换为状态j。有了这句话我们就可以根据现在构建出来的AC树可行的转移路径构建一个转移方程了,部分代码是

void BuildMatrix()    {        memset(mm.m, 0, sizeof(mm.m));        for(int i=0; i

三个判断条件分别约束的是,状态i,j都存在,状态i代表的子串不是病毒串,状态j代表的子串不是病毒串。

于是我们可以通过一步从状态i转移到状态j,矩阵记录的是转移的方案数,于是++;

接下来回到我们的问题是要长度为m,即由根节点转移m步,于是对一步可到达矩阵求m次幂可得到m步可到达矩阵,再将第0行加起来,即是从根节点m步可以到达的状态

代码如下:

#include
#include
#include
#include
#include
using namespace std;#define mod 100000int m, n;int cnt['Z'+1];struct MM{ long long m[110][110];};MM mm;MM m1, m2;void init(){ cnt['A'] = 0; cnt['T'] = 1; cnt['C'] = 2; cnt['G'] = 3;}MM mul(MM a, MM b, int siz){ MM c; memset(c.m, 0, sizeof(c.m)); for(int k=0; k
Q; int now; fail[root] = root; for(int i=0; i<4; i++) { if(nex[root][i] == -1) { nex[root][i] = root; } else { fail[nex[root][i]] = root; Q.push(nex[root][i]); } } while( !Q.empty() ) { now = Q.front(); Q.pop(); if(en[fail[now]] != 0) { en[now] = 1; } for(int i=0; i<4; i++) { if(nex[now][i] == -1) { nex[now][i] = nex[fail[now]][i]; } else { fail[nex[now][i]] = nex[fail[now]][i]; Q.push(nex[now][i]);// if(en[fail[nex[now][i]]] != 0)// {// en[nex[now][i]] = 1;///en数组的值为1就不能走 为1代表是一个串的结尾 就不能走 为什么这个字符的fail指向一个en[]不为0的就也要置成不为0呢// ///因为一个病毒串是这个串的后缀 那么这个串虽然不是病毒串 到那时后半部分含有病毒串// ///为什么只要考虑与他直接相连的字符的fail值就可以了呢 因为可以抽象的理解为 fail一定是在他的上面的层 一定不在同一层 因为如果在同一层 则这两个串是一样的 饿就好似同一个串// ///这种情况是不会发生的 同时build()函数是从根节点发出的 保证了上面层的en数组都已经更新完成 具有传递的特质 所以只要考虑直接连接的fail值即可// } } } }// for(int i=0; i

 

转载于:https://www.cnblogs.com/Flower-Z/p/9485637.html

你可能感兴趣的文章
初学者自学前端须知
查看>>
Retrofit 源码剖析-深入
查看>>
企业级负载平衡简介(转)
查看>>
ICCV2017 论文浏览记录
查看>>
科技巨头的交通争夺战
查看>>
当中兴安卓手机遇上农行音频通用K宝 -- 卡在“正在通讯”,一直加载中
查看>>
Shell基础之-正则表达式
查看>>
JavaScript异步之Generator、async、await
查看>>
讲讲吸顶效果与react-sticky
查看>>
c++面向对象的一些问题1 0
查看>>
直播视频流技术名词
查看>>
iOS13-适配夜间模式/深色外观(Dark Mode)
查看>>
网易跟贴这么火,背后的某个力量不可忽视
查看>>
企业级java springboot b2bc商城系统开源源码二次开发-hystrix参数详解(八)
查看>>
java B2B2C 多租户电子商城系统- 整合企业架构的技术点
查看>>
IOC —— AOP
查看>>
比特币现金将出新招,推动比特币现金使用
查看>>
数据库的这些性能优化,你做了吗?
查看>>
某大型网站迁移总结(完结)
查看>>
mysql的innodb中事务日志(redo log)ib_logfile
查看>>