热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[POJ2778]DNASequence(AC自动机+DP+矩阵加速)

DescriptionItswellknownthatDNASequenceisasequenceonlycontainsA,C,TandG,anditsver
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


禁止字符串,求长度为n的不包含模板串的字符串有多少个。典型的AC自动机+DP的题目。dp[ i ][ np ] 表示字符串构造到第 i 位且此时trie上匹配到了第np个点。 枚举第 i+1 个字母,碰到失配的时候fail回去并转移(已优化) ,碰到结尾的时候无视之,其余转移。

由于n比较大,需要用矩阵快速幂加速DP。构造矩阵: n [nxp][np] = 1 表示有一个状态可以从 trie 上的 np 的位置转移到下一个 nxp 的位置。然后快速幂之。


本题坑点:

(1)这题在POJ上时限卡的比较紧。所以必要的时候再MOD,不然会T。(或者是我自己常数写得不够美) 


#include 
#include
#include

using namespace std;
const int nxtsize = 4, noden = 10*10+10, MOD = 100000;
int chn(char a)
{
switch(a)
{
case 'A': return 0;
case 'T': return 1;
case 'C': return 2;
case 'G': return 3;
}
}

struct trnode
{
char chr;
int nxt[4],fail,val;
};

struct Matrix
{
Matrix();
Matrix(int size){memset(n, 0, sizeof(n));sz=size;}
int sz;
long long n[noden][noden];
void E(){for(int i=0; i/*
void pri()
{
for(int i=0; i<=sz; i++)
{
for(int j=0; j<=sz; j++)
printf("%I64d ", this->n[i][j]);
puts("");
}
}
*/
};


int n,m;
int triep;
trnode trie[noden];
int que[noden];

void addstr(char*);
void calfail();
Matrix operator * (Matrix, Matrix);
Matrix mtxpow(Matrix,int);

int main()
{
scanf("%d %d\n", &m, &n);
for(int i=0; i{
char patn[11];
scanf("%s", patn);
addstr(patn);
}
calfail();
Matrix ans(triep);
for(int np=0; np<=triep; np++)
{
if(trie[np].val) continue;
for(int k=0; k{
int nxp = trie[np].nxt[k];
if(trie[nxp].val) continue;
ans.n[nxp][np] ++;
}
}
ans = mtxpow(ans,n);
long long outp = 0;
for(int i=0; i<=triep; i++)
{
if(trie[i].val) continue;
outp += ans.n[i][0];
}
printf("%I64d\n", outp%MOD);
return 0;
}

void addstr(char *patn)
{
int len = strlen(patn);
int np = 0;
for(int i=0; i{
int nxp = trie[np].nxt[chn(patn[i])];
if(nxp)
np = nxp;
else
{
triep++;
trie[np].nxt[chn(patn[i])] = triep;
np = triep;
trie[np].chr = patn[i];
}
if(i==len-1) trie[np].val = 1;
}
return;
}

void calfail()
{
int qhead=0, qtail=0;
for(int i=0; iif(trie[0].nxt[i])
que[++qtail] = trie[0].nxt[i];
while(qhead{
int np = que[++qhead];
for(int i=0; i{
int nxp = trie[np].nxt[i];
int fap = trie[np].fail;
if(!nxp)
{
trie[np].nxt[i] = trie[fap].nxt[i];
continue;
}
que[++qtail] = nxp;
trie[nxp].fail = trie[fap].nxt[i];
fap = trie[nxp].fail;
if(trie[fap].val) trie[nxp].val = 1;
}
}
return;
}

Matrix operator * (Matrix a, Matrix b)
{
int sz = a.sz;
Matrix tem(sz);
for(int i=0; i<=sz; i++)
for(int j=0; j<=sz; j++)
for(int k=0; k<=sz; k++)
{
tem.n[i][j] += a.n[i][k]*b.n[k][j];
tem.n[i][j] %= MOD;
}
return tem;
}

Matrix mtxpow(Matrix cal, int t)
{
Matrix tem(cal.sz);
tem.E();
while(t)
{
if(t&1)
tem=tem*cal;
cal=cal*cal;
t>>=1;
}
return tem;
}



推荐阅读
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
author-avatar
叶毒手_938
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有