[poj2778]DNA Sequence(AC自动机+矩阵快速幂)

解题关键:卡时限过的,正在找原因中。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<queue>
  8 using namespace std;
  9 typedef long long ll;
 10 const int N=4;
 11 const int MAXN=101;
 12 struct mat{
 13     ll m[101][101];
 14 };
 15 ll m,n;
 16 ll mod=100000;
 17 struct Trie{
 18     int Next[MAXN][N],Fail[MAXN],root,tot;
 19     bool End[MAXN];
 20     int newnode(){
 21         for(int i=0;i<N;i++) Next[tot][i]=-1;
 22         End[tot++]=false;
 23         return tot-1;
 24     }
 25     void init(){
 26         tot=0;
 27         root=newnode();
 28     }
 29     void insert(char buf[]){
 30         int len=strlen(buf),now=root,k;
 31         for(int i=0;i<len;i++){
 32             if(buf[i]==‘A‘) k=0;
 33             else if(buf[i]==‘G‘) k=1;
 34             else if(buf[i]==‘C‘) k=2;
 35             else k=3;
 36             if(Next[now][k]==-1)  Next[now][k]=newnode();
 37             now=Next[now][k];
 38         }
 39         End[now]=true;
 40     }
 41     void build(){
 42         queue<int>que;
 43         Fail[root]=root;
 44         for(int i=0;i<N;i++){
 45             if(Next[root][i]==-1) Next[root][i]=root;
 46             else{
 47                 Fail[Next[root][i]]=root;
 48                 que.push(Next[root][i]);
 49             }
 50         }
 51         while(!que.empty()){
 52             int now=que.front();
 53             que.pop();
 54             if(End[Fail[now]]) End[now]=true;
 55             for(int i=0;i<N;i++){
 56                 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i];
 57                 else{
 58                     Fail[Next[now][i]]=Next[Fail[now]][i];
 59                     que.push(Next[now][i]);
 60                 }
 61             }
 62         }
 63     }
 64     mat get_mat(int len){
 65         mat B={0};
 66         for(int i=0;i<len;i++){
 67             for(int j=0;j<N;j++){
 68                 if(End[Next[i][j]]==false) B.m[i][Next[i][j]]++;//不能直接置1
 69             }
 70         }
 71         return B;
 72     }
 73 };
 74
 75 mat mul(mat &A,mat &B,int len){
 76     mat C={0};
 77     for(int i=0;i<len;i++){
 78         for(int k=0;k<len;k++){
 79             for(int j=0;j<len;j++){
 80                 C.m[i][j]=(C.m[i][j]+A.m[i][k]*B.m[k][j]%mod)%mod;
 81             }
 82         }
 83     }
 84     return C;
 85 }
 86
 87 mat pow(mat A,ll n,int len){
 88     mat B={0};
 89     for(int i=0;i<len;i++) B.m[i][i]=1;
 90     while(n){
 91         if(n&1) B=mul(B,A,len);
 92         A=mul(A,A,len);
 93         n>>=1;
 94     }
 95     return B;
 96 }
 97
 98 Trie ac;
 99 char buf[10];
100 int main(){
101     while(scanf("%lld%lld",&m,&n)!=EOF){
102         ac.init();
103         for(int i=0;i<m;i++){
104             scanf("%s",buf);
105             ac.insert(buf);
106         }
107         ac.build();
108         mat B=ac.get_mat(ac.tot);
109         B=pow(B,n,ac.tot);
110         ll res=0;
111         for(int i=0;i<ac.tot;i++){
112             res=(res+B.m[0][i])%mod;
113         }
114         printf("%lld\n",res);
115     }
116     return 0;
117 } 
时间: 2024-10-21 18:52:43

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

POJ POJ 2778 DNA Sequence AC自动机 + 矩阵快速幂

首先建立Trie和失败指针,然后你会发现对于每个节点 i 匹配AGCT时只有以下几种情况: i 节点有关于当前字符的儿子节点 j 且安全,则i 到 j找到一条长度为 1的路. i 节点有关于当前字符的儿子节点 j 且 不安全,则i 到 j没有路. i 节点没有关于当前字符的儿子节点 但是能通过失败指针找到一个安全的节点j,那么 i 到 j 找到一条长度为1的路. 关于节点安全的定义: 当前节点不是末节点且当前节点由失败指针指回跟节点的路径上不存在不安全节点,那么这个节点就是安全节点. 然后问题就

poj 2778 DNA Sequence(AC自动机+矩阵快速幂)

题目链接:poj 2778 DNA Sequence 题目大意:给定一些含有疾病的DNA序列,现在给定DNA长度,问有多少种不同的DNA序列是健康的. 解题思路:对DNA片段建立AC自动机,因为最多10个串,每个串最长为10,所以最多可能有100个节点,在长度为n时 以每个节点终止的健康字符串个数形成一个状态集,通过AC自动机形成的边可以推导出n+1的状态集,走到单词节点是 非法的,所以同样的我们可以先走到单词节点,但是从单词节点不向后转移.这样可以构造一个矩阵,剩下的就是矩阵 快速幂.注意的一

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

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K 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 DN

hdu 2243 AC自动机 + 矩阵快速幂

// hdu 2243 AC自动机 + 矩阵快速幂 // // 题目大意: // // 给你一些短串,问在长度不超过k的任意串,包含至少一个这些短串的其中 // 一个.问这样的串有多少个. // // 解题思路: // // 首先, 包含和不包含是一种互斥关系,包含+不包含 = 全集u.全集的答案就是 // 26 ^ 1 + 26 ^ 2 + .... + 26 ^ k.不包含的比较好求.构建一个自动机,得到 // 一个转移矩阵A.表示状态i能到状态j的方法数.而这些状态中都是不包含所给的 //

HDU 2243 考研路茫茫――单词情结 (AC自动机 + 矩阵快速幂)

题目链接:考研路茫茫――单词情结 做本题前,个人建议先做一下POJ 2778 http://blog.csdn.net/u013446688/article/details/47378255 POJ2778 是求长度为n,不包含模式串的字符串个数. 而本题是求长度为n,包含模式串的字符串个数.直接用字符串总数减去不包含模式串的字符串个数即为所求. 同样是AC自动机 + 矩阵快速幂.但是还是有所不同的. 因为对2^64取模,所以定义数据类型为unsigned long long就可以了,这样就实现

poj 2778 AC自动机 + 矩阵快速幂

// poj 2778 AC自动机 + 矩阵快速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自动机,确定状态之间的关系,构造出,走一步 // 能到达的状态矩阵,然后进行n次乘法,就可以得到状态间 // 走n步的方法数. // 精髓: // 1):这个ac自动机有一些特别,根节点是为空串,然而 // 每走一步的时候,如果没法走了,这时候,不一定是回到根 // 节点,因为有可能单个的字符时病毒,这样

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

题目链接:DNA Sequence 解析:AC自动机 + 矩阵加速(快速幂). 这个时候AC自动机 的一种状态转移图的思路就很透彻了,AC自动机就是可以确定状态的转移. AC代码: #include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; const int MOD = 100000; struct Matrix{ int ma

poj2778 ac自动机+矩阵快速幂

给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://wenku.baidu.com/view/d7b9787f1711cc7931b716b0.html 对于a(i,j)^k  是指从i到j经过k个点的所有情况数 注意对于End数组,如果某个节点如果fail指针End数组为1,那么End[该节点]也是1 string要开全局变量,不然不能运行= = #i

POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂

这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的tire图详解可以点击这里,往下面翻,这个博主的图对于tire图讲的非常详细. 知道了什么是tire图,理解了tire图后,后面的AC自动机的题目才能写. AC自动机的灵魂应该就是tire图 然后问题就变成了,得到了一个可达矩阵后,如何求方案数呢? 这个n = 2000000000 这咋办呢? 给定一