题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。(仅含A,T,C,G四个字符)

解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模,尤其是在快速幂的时候,消耗时间极其巨大,此题效率差10倍。

先+=在进行取模,两者分开,也可以快1倍。

按照AC自动机建立邻接矩阵,其中不含病毒模式串的位置可以到达,

其中上图矩阵为:

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

去掉病毒结点之后,变为

2 1

2 1

转移方程:$dp[u] = \sum\limits_{v -  > u} {dp[v]} $

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
const int N=;
const int MAXN=;
struct mat{
ll m[][];
};
ll m,n;
ll mod=;
struct Trie{
int Next[MAXN][N],Fail[MAXN],root,tot;
bool End[MAXN];
int newnode(){
for(int i=;i<N;i++) Next[tot][i]=-;
End[tot++]=false;
return tot-;
}
void init(){
tot=;
root=newnode();
}
void insert(char buf[]){
int len=strlen(buf),now=root,k;
for(int i=;i<len;i++){
if(buf[i]=='A') k=;
else if(buf[i]=='G') k=;
else if(buf[i]=='C') k=;
else k=;
if(Next[now][k]==-) Next[now][k]=newnode();
now=Next[now][k];
}
End[now]=true;
}
void build(){
queue<int>que;
Fail[root]=root;
for(int i=;i<N;i++){
if(Next[root][i]==-) Next[root][i]=root;
else{
Fail[Next[root][i]]=root;
que.push(Next[root][i]);
}
}
while(!que.empty()){
int now=que.front();
que.pop();
if(End[Fail[now]]) End[now]=true;
for(int i=;i<N;i++){
if(Next[now][i]==-) Next[now][i]=Next[Fail[now]][i];
else{
Fail[Next[now][i]]=Next[Fail[now]][i];
que.push(Next[now][i]);
}
}
}
}
mat get_mat(int len){
mat B={};
for(int i=;i<len;i++){
for(int j=;j<N;j++){
if(End[Next[i][j]]==false) B.m[i][Next[i][j]]++;//不能直接置1
}
}
return B;
}
}; mat mul(mat &A,mat &B,int len){
mat C={};
for(int i=;i<len;i++){
for(int j=;j<len;j++){
for(int k=;k<len;k++){
C.m[i][j]+=A.m[i][k]*B.m[k][j];
}
C.m[i][j]%=mod;
}
}
return C;
} mat pow(mat A,ll n,int len){
mat B={};
for(int i=;i<len;i++) B.m[i][i]=;
while(n){
if(n&) B=mul(B,A,len);
A=mul(A,A,len);
n>>=;
}
return B;
} Trie ac;
char buf[];
int main(){
while(scanf("%lld%lld",&m,&n)!=EOF){
ac.init();
for(int i=;i<m;i++){
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
mat B=ac.get_mat(ac.tot);
B=pow(B,n,ac.tot);
ll res=;
for(int i=;i<ac.tot;i++){
res+=B.m[][i];
}
printf("%lld\n",res%mod);
}
return ;
}

[poj2778]DNA Sequence(AC自动机+矩阵快速幂)的更多相关文章

  1. poj2778 DNA Sequence(AC自动机+矩阵快速幂)

    Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's ve ...

  2. poj 2778 DNA Sequence ac自动机+矩阵快速幂

    链接:http://poj.org/problem?id=2778 题意:给定不超过10串,每串长度不超过10的灾难基因:问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中? DN ...

  3. poj2778DNA Sequence (AC自动机+矩阵快速幂)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud DNA Sequence Time Limit: 1000MS   Memory ...

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

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

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

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

  6. 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 ...

  7. DNA Sequence POJ - 2778 AC自动机 && 矩阵快速幂

    It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to ...

  8. POJ 2778 DNA Sequence(AC自动机 + 矩阵快速幂)题解

    题意:给出m个模式串,要求你构造长度为n(n <= 2000000000)的主串,主串不包含模式串,问这样的主串有几个 思路:因为要不包含模式串,显然又是ac自动机.因为n很大,所以用dp不太好 ...

  9. POJ2778(SummerTrainingDay10-B AC自动机+矩阵快速幂)

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17160   Accepted: 6616 Des ...

随机推荐

  1. django(一)--- 安装django

    准备好虚拟环境:Python开发虚拟环境 安装前的准备 1. 下载django:django下载 本文使用的是django-1.5.9(不同版本号之间的差别还是比較大的.别搞错了) 2.准备djang ...

  2. sass的使用(载)

    一.什么是SASSSASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护.本文总结了SASS的主要用法.我的目标是,有了这篇文章,日常的一般使 ...

  3. Maven - 下载JAR包

    进入Spring官网http://projects.spring.io/spring-framework/假设我们想下载Spring发现仅仅能 通过Maven或Cradle进行下载了. 以下以Spri ...

  4. Thrift安装介绍

    一.简介 1.语言库要求 因为thrift支持多语言.所以编译thrift源代码的过程中,会用到该语言的一些类库.如c++的boost.java的jdk等. 那么,在安装thrift过程中,须要对各种 ...

  5. Matlab---傅里叶变换---通俗理解(二)

    1.用Matlab进行傅立叶变换 FFT是离散傅里叶变换的高速算法,能够将一个信号变换到频域.有些信号在时域上是非常难看出什么特征的,可是假设变换到频域之后,就非常easy看出特征了.这就是非常多信号 ...

  6. 简单的HTML5音乐播放器(带歌词滚动)

      // // 0) { this.lrcArr.push(item); } } frag = document.createDocumentFragment(); for(i = 0,len = t ...

  7. C# 通过Hook的方法 屏蔽快捷键

     #region 屏蔽Windows功能键(快捷键)         public delegate int HookProc(int nCode, int wParam, IntPtr lParam ...

  8. OpenCV 的四大模块

    前言 我们都知道 OpenCV 是一个开源的计算机视觉库,那么里面到底有哪些东西?本文将为你解答这个问题. 模块一:CV 这个模块是 OpenCV 的核心,它包含了基本的图像处理函数和高级的计算机视觉 ...

  9. cURL实现Get和Post

    1.Get请求: //初始化 $ch = curl_init(); //设置选项,包括URL curl_setopt($ch, CURLOPT_URL, "http://www.jb51.n ...

  10. 利用crtmpserver搭建rtmp服务器

    Google + 实践:最终直播成功. 记录一下. 这样.兴许就能够对代码进行改造,利用开源码实现:Android平台下.搭建rtmpserver.浏览器端利用flash播放视频. 代码架构为:ffm ...