【POJ No. 2778】DNA 序列 DNA Sequence

北大OJ 题目地址

【题意】

DNA序列是一个只包含A、C、T和G的序列。分析DNA序列片段非常有用,若动物的DNA序列包含片段ATC,则意味着该动物可能患有遗传病。

给定m 个遗传病片段,求有多少种长度为n 的DNA序列不包含这些片段。

【输入输出】

输入:

第1行包含两个整数m (0≤m ≤10)和n (1≤n ≤2×109)。m 是遗传病片段的数量,n 是序列的长度。接下来的M 行,每行都包含一个DNA遗传病片段(长度不大于10)。

输出:

一个整数,不包含遗传病的DNA序列数mod 100000。

【样例】

【思路分析】

DNA序列只包含A、G、C、T共4种字母,给定m 个DNA遗传病片段,求有多少长度为n 的DNA序列不包含遗传病片段,可采用AC自动机解决。

【算法设计】

① 将遗传病片段插入字典树中。

② 构建AC自动机。注意:若当前节点的失败指针有结束标记,则对当前节点也要标记。

③ 构建邻接矩阵。对所有未标记的节点都重新编号,根据AC自动机构建邻接矩阵。

④ 求解矩阵的n 次幂,可用矩阵快速幂求解。

【举个栗子】

求解答案和矩阵有什么关系呢?

假设遗传病片段为{“ACG”, “C”},则将两个字符串插入字典树中并构建AC自动机。

从每个节点出发的边有4条(A、T、C、G)。

从状态0出发走1步有4种走法:①走A到状态1(安全);②走C到状态4(危险);③走T到状态0(安全);④走G到状态0(安全)。所以当n =1时,答案是3。

当n =2时,从状态0出发走2步,形成一个长度为2的字符串,只要在路径上没有经过危险节点,则有几种走法,答案就是几种。以此类推走n 步,就形成长度为n 的字符串。

这实际上相当于二元关系的复合运算,可以用图论里面的邻接矩阵相乘求解。

对上图的AC自动机建立邻接矩阵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 只走1步有几种走法,M 的n 次幂表示从节点i 到j 走n 步有几种走法。

注意:要去掉危险节点的行和列。节点3和4是遗传病片段的结尾,是危险节点,节点2的失败指针指向4,当匹配“AC”时也就匹配了“C”,所以2也是危险节点。去掉危险节点2、3、4后,邻接矩阵变成M :

2 1
2 1

计算M[][]的n 次幂,∑(M[0, i ]) mod 100000就是答案。由于n很大,所以使用矩阵快速幂计算矩阵的n 次幂。

【算法实现】

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>using namespace std;const int maxn=105;
const int K=4;
const int MOD=100000;struct mat{int a[maxn][maxn];mat(){memset(a,0,sizeof(a));}
};
int root,L;mat mul(mat A,mat B){//矩阵乘法mat C;for(int i=0;i<L;i++)for(int j=0;j<L;j++)for(int k=0;k<L;k++)C.a[i][j]=(C.a[i][j]+(long long)A.a[i][k]*B.a[k][j])%MOD;return C;
}mat pow(mat A,int n){//A^nmat ans;for(int i=0;i<L;i++)ans.a[i][i]=1;//单位矩阵 while(n>0){if(n&1)ans=mul(ans,A);A=mul(A,A);n>>=1;}return ans;
}struct ACAutomata{int next[maxn][K],fail[maxn],end[maxn],id[maxn];int idx(char ch){//转化数字switch(ch){case 'A':return 0;case 'C':return 1;case 'T':return 2;case 'G':return 3;}return -1;}int newNode(){//新建结点 for(int i=0;i<K;i++)next[L][i]=-1;end[L]=0;return L++;}void init(){//初始化L=0;root=newNode();}void insert(char s[]){//插入一个结点int len=strlen(s);int p=root;for (int i=0;i<len;i++){int ch=idx(s[i]);if(next[p][ch]==-1)next[p][ch]=newNode();p=next[p][ch];}end[p]++;}void build(){//构建AC自动机queue<int> Q;fail[root]=root;for(int i=0;i<K;i++){if(next[root][i]==-1){next[root][i]=root;}else{fail[next[root][i]]=root;Q.push(next[root][i]);}}while(Q.size()){int now=Q.front();Q.pop();if(end[fail[now]])end[now]++;//重要!!如果当前结点的失败指针end有结束标记,当前结点的end++ for(int i=0;i<K;i++){if(next[now][i]!=-1){fail[next[now][i]]=next[fail[now]][i];Q.push(next[now][i]);}elsenext[now][i]=next[fail[now]][i];}}}int query(int n){mat F;int ids=0;memset(id,-1,sizeof(id));for(int i=0;i<L;i++)//对未标记的结点重新编号 if(!end[i])id[i]=ids++;for(int u=0;u<L;u++){if(end[u]) continue;for(int j=0;j<K;j++){int v=next[u][j];if(!end[v])F.a[id[u]][id[v]]++;}}L=ids;F=pow(F,n);int res=0;for(int i=0;i<L;i++)res=(res+F.a[0][i])%MOD;return res;}
}ac;int main(){int m,n;char str[20];while(~scanf("%d%d",&m,&n)){ac.init();while (m--){scanf("%s",str);ac.insert(str);}ac.build();printf("%d\n",ac.query(n));}return 0;
}

【POJ No. 2778】DNA 序列 DNA Sequence相关推荐

  1. numpy序列预处理dna序列_使用机器学习和Python揭开DNA测序神秘面纱

    "脱氧核糖核酸(DNA)是一种分子,其中包含每个物种独特的生物学指令.DNA及其包含的说明在繁殖过程中从成年生物传给其后代." 简介 基因组是生物体中DNA的完整集合.所有生物物种 ...

  2. HDU 1560 DNA sequence(DNA序列)

    HDU 1560 DNA sequence(DNA序列) Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K  ...

  3. DNA序列编码中Hairpin的定义和计算

    DNA序列编码中Hairpin的定义和计算 觉得有用的话,欢迎一起讨论相互学习~ 参考文献 [1] 张凯. DNA计算核酸编码优化及算法设计[D]. 2008. [2] Shin, Soo Yong ...

  4. 基因家族进化分析之DNA序列批量获取

    使用方法参考: 基于全基因组的基因家族分析(3):SlNRAMP家族基因CDS和Genomic DNA序列获取 Gene序列要获得的ID号不仅仅是seqid,而且还需要在染色体上的位置信息--起始和终 ...

  5. DNA序列存储为tfr文件并读取

    最近导师让我跑模型,生物信息方向的,我一个学计算机的,好多东西都看不明白.现在的方向大致是,用深度学习的模型预测病毒感染人类的风险. 既然是病毒,就需要拿到它的DNA,也就是碱基序列,然后把这些ACG ...

  6. 利用python处理dna序列_Python + 生物信息 02 :Biopython 分析序列

    Biopython 做序列分析 一.安装Biopython:如果环境已经有Biopython可以跳过这一步.这里有两种安装方案,一种通过pip快速安装,另一种通过安装包安装 1. 用pip安装Biop ...

  7. 使用pysam读取DNA序列

    先创建一个读对象: fasta_open = pysam.Fastafile(fasta_file) 读出来的DNA序列是字符串的格式: seq_dna = fasta_open.fetch('chr ...

  8. 字符串(如DNA序列,蛋白质序列)的编码和用于机器学习和神经网络

    在处理dna序列或这蛋白质序列时,常常需要把序列转化为数字,这样才能形成矩阵输入模型训练,一般而言,有三种方法用于序列编码:顺序编码,独热编码,kmer编码. 1. 顺序编码 第一种顺序编码即使把at ...

  9. numpy序列预处理dna序列_【陪你学生信】七、在数据库中检索相似的序列

    一.相似度Similarity 序列的分析离不开相似度这个指标,相似度比较高的序列往往具有相似的结构.执行相似的功能.所以用未知序列blast得到的结果可以对未知序列进行推测. 当两个序列非常相似时, ...

最新文章

  1. 抽屉效果----mmdrawercontroller和viewdeck
  2. Mybatis系列:解决foreach标签内list为空的问题
  3. Win10如何找出占用硬盘空间大的文件及怎么删除
  4. Python基础:集合与文件操作
  5. layui的table常用方法
  6. java stax_XMLStreamWriter Java StAX
  7. exchange server 2010 OWA 附件功能只支持IE浏览器
  8. Firefox火狐浏览器怎么设置中文 火狐浏览器语言设置方法
  9. 无线通信中的IQ调制,BPSK调制,QPSK调制,16QAM调制的理解
  10. 计算机应用参考文献,计算机应用领域英文参考文献 哪里有计算机应用领域参考文献...
  11. 基础体温软件测试,[快乐备孕][备孕攻略]使用基础体温测量软件,志在必得的备孕...
  12. GPU深度发掘 -- GPGPU数学基础教程
  13. wannier拟合能带总是拟合不上_科学网-Wannier90输入文件中num_wann, num_bands, 和energy window等参数设置规则-李云海的博文...
  14. 2019年内大892数据结构部分参考答案
  15. 戴尔服务器如何设置自动开关机,Dell服务器的IPMI/iKVM使用方法(开机,关机,重启,重装系统)...
  16. 我的世界神秘时代安卓java版_我的世界神秘时代4
  17. 求最小公倍数【牛客网】
  18. idea试用许可证过期的问题
  19. Zynq7020_PS端 uart驱动编写及Vivadio-SDK配置
  20. python属于计算机的什么语言_Python语言属于()_学小易找答案

热门文章

  1. Day5 快速输入数据的方法
  2. JavaScript传参的6种方式
  3. 报童问题求解最大利润_钢管下料问题模型
  4. PDF文件怎么复制页面,复制页面工具使用方法
  5. Wireshark提取RTP包中的H264码流
  6. 计算机操作系统汤晓丹第四版+指导解析
  7. 【深度神经网络】五、GoogLeNet网络详解
  8. unity网络实战开发(丛林战争)-前期知识准备(010-在服务器端解析数据)
  9. 【Python与SEO】搜狗微信搜索下拉框词采集多线程/异步采集源码公布
  10. python程序员面试自我介绍_「日语面试自我介绍」程序员日语自我介绍 - seo实验室...