DNA Sequence POJ - 2778 AC自动机 && 矩阵快速幂
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
Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.
Output
Sample Input
4 3
AT
AC
AG
AA
Sample Output
36
题意:
多组输入,n代表下面有n个模式串。m代表你要构造的DNA序列长度
题目让你求DNA序列为m,序列中不出现以上n个模式串的DNA序列有多少
题解:
我的上一代码用的我自己写的矩阵快速幂,那个版本每次都要初始化数组,太耗时了就TLE。找了个结构体版本的快速幂
这一道题就是问你你能找到多少个长度最长为m的正常DNA序列(什么叫正常?就是不含病毒的那种)
对于矩阵(这里以2*2为例)
|X(11) X(12)|
|X(21) X(22)|
我们设我们构造的矩阵为ans,其中ans[i][j]表示DNA序列中从i节点到j节点(下面都直接称为i、j)走一步的方法数(就是最后找出来的DNA序列中第i个位置和第j个
个位置,因为是一步,所以i和j在DNA序列中是相邻的。可以构成正常DNA的方法数)
什么叫i、j节点,我们在构造字典树的过程中会产生节点,那个节点是第几个产生的,那个就是它的序号
然后矩阵的二次方的ans[i][j]的意思就是从DNA序列中从i先到一个中转点再到j有多少种DNA序列满足
那么矩阵的n次方的ans[i][j]意思就是DNA序列中从i到n个中转点再到j有多少种DNA序列满足
那么我们只需要求出来ans[i][j]DNA序列中从i走一步的j这一段在DNA序列中方案数
然后这个矩阵求m次方就可以了
ans[i][j]DNA序列中从i走一步的j这一段在DNA序列中方案数的这个ans矩阵怎么求?
把每一个病毒串的终止位置给标记了,在字典树上通过失败指针跳转如果能到病毒串终止位置也要把这个点标记了,然后沿着字典树的next数组跑一边就完了(具体看代码)
然后第一行ans[0][1],ans[0][1]...ans[0][99]的所有数的和就可以了
ans[0][1]的意思就是从DNA序列0号位置(即,开头)经过m-1个中转点到1号节点 //0号位置是字典树根的位置,所以不算在DNA序列内
这个样子加起来就是答案
为什么可以这样做?
ans[i][j]最初的一步矩阵:
他就代表i这个点后面可以往j这个位置走一步有多少种不重复走法
ans[i][j]的m次方矩阵:
相当于字典树就是一个有向图,你就沿着它的方向跑下去。每跑m路程就会有一个对应DNA序列,又因为你已经把病毒串终止位置标记了,所以根本不可能跑到那个位置。所以你跑出来的DNA序列中也不会包含病毒序列
代码:
1 #include<stdio.h>
2 #include<iostream>
3 #include<string.h>
4 #include<algorithm>
5 #include<queue>
6 using namespace std;
7 const int maxn=115;
8 const int N=4;
9 const int mod=100000;
10 typedef long long ll;
11 int n,m;
12 int w[120];
13 struct Matrix
14 {
15 int mat[maxn][maxn],n;
16 Matrix() {}
17 Matrix(int _n)
18 {
19 n = _n;
20 for(int i=0; i<n; i++)
21 for(int j=0; j<n; j++)
22 mat[i][j]=0;
23 }
24 Matrix operator *(const Matrix &b)const
25 {
26 Matrix ret=Matrix(n);
27 for(int i=0; i<n; i++)
28 for(int j=0; j<n; j++)
29 for(int k=0; k<n; k++)
30 {
31 int tmp=(long long)mat[i][k]*b.mat[k][j]%mod;
32 ret.mat[i][j]=(ret.mat[i][j]+tmp)%mod;
33 }
34 return ret;
35 }
36 };
37 struct Trie
38 {
39 int next[maxn][N],fail[maxn],ends[maxn];
40 int root,L;
41 int New_node() //创建一个新节点
42 {
43 for(int i=0; i<N; ++i)
44 {
45 next[L][i]=-1;
46 }
47 ends[L++]=0;
48 return L-1;
49 }
50 void init() //创建根节点
51 {
52 L=0;
53 root=New_node();
54 }
55 void inserts(char s[]) //往字典树里面插入新字符串
56 {
57 int len=strlen(s);
58 int now=root;
59 for(int i=0; i<len; ++i)
60 {
61 if(next[now][w[s[i]]]==-1)
62 next[now][w[s[i]]]=New_node();
63 now=next[now][w[s[i]]];
64 }
65 ends[now]=1; //病毒串终点要标记
66 }
67 void build()
68 {
69 queue<int>r;
70 fail[root]=root;
71 for(int i=0; i<N; ++i)
72 {
73 if(next[root][i]==-1)
74 {
75 next[root][i]=root;
76 }
77 else
78 {
79 fail[next[root][i]]=root;
80 r.push(next[root][i]);
81 }
82 }
83 while(!r.empty())
84 {
85 int now=r.front();
86 r.pop();
87 if(ends[fail[now]]) //如果now节点的失败指针指向病毒串终点,那么也要把now这个点给标记了
88 {
89 ends[now]=1;
90 }
91 for(int i=0; i<N; ++i)
92 {
93 if(next[now][i]==-1)
94 {
95 next[now][i]=next[fail[now]][i];
96 }
97 else
98 {
99 fail[next[now][i]]=next[fail[now]][i];
100 r.push(next[now][i]);
101 }
102 }
103 }
104 }
105 Matrix Build_c()
106 {
107 Matrix res=Matrix(L);
108 for(int i=0; i<L; ++i)
109 {
110 for(int j=0; j<N; ++j)
111 {
112 if(ends[next[i][j]]==0) //创建走一步的ans矩阵
113 {
114 res.mat[i][next[i][j]]++;
115 }
116 }
117 }
118 return res;
119 }
120 };
121 char s[20];
122 Trie ac;
123 Matrix pow_M(Matrix a,int n)
124 {
125 Matrix ret = Matrix(a.n);
126 for(int i = 0; i < ret.n; i++)
127 ret.mat[i][i]=1;
128 Matrix tmp=a;
129 while(n)
130 {
131 if(n&1)ret=ret*tmp;
132 tmp=tmp*tmp;
133 n>>=1;
134 }
135 return ret;
136 }
137 int main()
138 {
139 w['A']=0;
140 w['C']=1;
141 w['G']=2;
142 w['T']=3;
143 while(~scanf("%d%d",&n,&m))
144 {
145 ac.init();
146 while(n--)
147 {
148 scanf("%s",s);
149 ac.inserts(s);
150 }
151 ac.build();
152 Matrix ans=ac.Build_c();
153 ans=pow_M(ans,m);
154 int sum=0;
155 for(int i=0; i<ac.L; ++i)
156 sum+=ans.mat[0][i],sum%=mod;
157 printf("%d\n",sum);
158 }
159 return 0;
160 }
DNA Sequence POJ - 2778 AC自动机 && 矩阵快速幂的更多相关文章
- poj 2778 AC自动机+矩阵快速幂
题目链接:https://vjudge.net/problem/POJ-2778 题意:输入n和m表示n个病毒,和一个长为m的字符串,里面只可以有'A','C','G','T' 这四个字符,现在问这个 ...
- DNA Sequence POJ - 2778 AC 自动机 矩阵乘法
定义重载运算的时候一定要将矩阵初始化,因为这个调了一上午...... Code: #include<cstdio> #include<algorithm> #include&l ...
- 考研路茫茫——单词情结 HDU - 2243 AC自动机 && 矩阵快速幂
背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...
- POJ 2778 DNA Sequence (ac自动机+矩阵快速幂)
DNA Sequence Description It's well known that DNA Sequence is a sequence only contains A, C, T and G ...
- POJ 2778 DNA Sequence(AC自动机 + 矩阵快速幂)题解
题意:给出m个模式串,要求你构造长度为n(n <= 2000000000)的主串,主串不包含模式串,问这样的主串有几个 思路:因为要不包含模式串,显然又是ac自动机.因为n很大,所以用dp不太好 ...
- POJ2778 DNA Sequence(AC自动机+矩阵快速幂)
题目给m个病毒串,问不包含病毒串的长度n的DNA片段有几个. 感觉这题好神,看了好久的题解. 所有病毒串构造一个AC自动机,这个AC自动机可以看作一张有向图,图上的每个顶点就是Trie树上的结点,每个 ...
- POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂
这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的t ...
- POJ 2778 (AC自动机+矩阵乘法)
POJ 2778 DNA Sequence Problem : 给m个只含有(A,G,C,T)的模式串(m <= 10, len <=10), 询问所有长度为n的只含有(A,G,C,T)的 ...
- poj2778DNA Sequence (AC自动机+矩阵快速幂)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud DNA Sequence Time Limit: 1000MS Memory ...
随机推荐
- 【分布式锁的演化】终章!手撸ZK分布式锁!
前言 这应该是分布式锁演化的最后一个章节了,相信很多小伙伴们看完这个章节之后在应对高并发的情况下,如何保证线程安全心里肯定也会有谱了.在实际的项目中也可以参考一下老猫的github上的例子,当然代码没 ...
- Linux 文件查看相关的一些命令
文件压缩解压命令 # 解压 xxx.xz 并删除 xz -d test.tar.xz # 打包成 xxx.tar , 语法: tar -cvf 最后包名.tar ./要打包文件 ./要打包的文件 ta ...
- 超过varchar定义长度
mysql> select version();+------------+| version() |+------------+| 5.1.73-log |+------------+1 ro ...
- 【设计模式】Java设计模式精讲之原型模式
简单记录 - 慕课网 Java设计模式精讲 Debug方式+内存分析 & 设计模式之禅-秦小波 文章目录 1.原型模式的定义 原型-定义 原型-类型 2.原型模式的实现 原型模式的通用类图 原 ...
- 【Linux】ethtool 用法
ethtool命令用于获取以太网卡的配置信息,或者修改这些配置.这个命令比较复杂,功能特别多. 语法 ethtool [ -a | -c | -g | -i | -d | -k | -r | -S | ...
- ctfshow——web_AK赛
签到_观己 从题目描述中没发现什么有用的信息 发现文件包含 尝试使用PHP伪协议执行命令,发现无法执行 尝试使用远程文件包含,发现也未开启 尝试使用日志注入 记录了UA值,抓包写入一句话木马 使用蚁剑 ...
- oracle创建恢复编录(recovery catalog)
1.在要作为恢复编录的数据库创建用户 create user rman identified by oracle default tablespace system temporary TABLESP ...
- 4、python+selenium实现12306模拟登录
简介: 这里是利用了selenium+图片识别验证,来实现12306的模拟登录,中间也参考了好几个项目,实现了这个小demo,中间也遇到了很多的坑,主要难点在于图片识别和滑动验证这两个方面,图片识别是 ...
- 使用Canal作为mysql的数据同步工具
一.Canal介绍 1.应用场景 在前面的统计分析功能中,我们采取了服务调用获取统计数据,这样耦合度高,效率相对较低,目前我采取另一种实现方式,通过实时同步数据库表的方式实现,例如我们要统计每天注册与 ...
- linux搭建ARM可调式环境
0x00 前言 本文中所介绍的方法目前只测试了单个的demo,并没有拿大型的项目做测试,但是应该是大同小异.这里介绍两种方法,一种是有独立的ARM硬件,另一种是依靠qemu实现的模拟化,其实其本质都是 ...