题意:

  给出患病的DNA序列,问序列长度为n的,且不包含患病的DNA序列有多少种

解析:

  以给出的患病DNA序列建trie树  患病结点要用flag标记

对于长度为n的序列 位置i有四种 情况A  C  T  G, buid的时候是从祖结点0开始的四种选择,如果tri树中存在某种选择,则顺着走下去,因为要防止恰好选择了患病DNA序列

若trie树中不存在某种选择,则指向0 即祖结点,因为这个点中断了患病DNA序列的生成

偷个图:https://blog.csdn.net/morgan_xww/article/details/7834801

危险结点要去掉,结点3和4是单词结尾所以危险,结点2的fail指针指向4,当匹配”AC”时也就匹配了”C”,所以2也是危险的。

解释一下为什么要去掉单词结尾

因为选择单词 结尾时必定是顺着树走下来的  比如说 如果选择了3  必定上一个是2  上上个是1

比如这次选择了3 而上一个是1  这种是不存在的  因为选了1后 这次想选3  而1在trie中 没有一步通向3的路  所以指向0结点 从0结点选

就是如果一个选择中断了患病DNA序列的生成  指向0就好了

矩阵i行j列的权值是结点i转移到结点j的方案数

而进行k次转移,从结点i转移到结点j的方案数是这个矩阵的k次幂

为什么?

首先解决这个问题:给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值

把给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的路径数,我们只需要二分求出A^k即可。

所以最后累加

    LL ret = ;
for(int i=; i<=tot; i++)
{
ret = (ret + A.v[][i]) % MOD;
}

枚举最后的节点是哪一个  因为起始节点肯定为0,而终止结点可以为0-tot的任何一个,所以累加从0到所有结点的方案数,即包含了所有情况

吐槽。。emm。。为什么函数的矩阵快速幂板子 结果是错了。。。。

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define MOD 100000
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = , maxm = , INF = 0x7fffffff;
int idx[];
int tot;
queue<int> q; struct Matrix
{
__int64 v[][];
Matrix()
{
memset(v, , sizeof(v));
}
Matrix operator *(const Matrix B) // 重载的速度比写独立的函数慢点。
{
int i, j, k;
Matrix C;
for(i = ; i <= tot; i ++)
for(j = ; j <= tot; j ++)
for(k = ; k <= tot; k ++)
{
C.v[i][j] = (C.v[i][j] + v[i][k] * B.v[k][j]) % MOD;
}
return C;
}
}; struct state
{
int next[];
int fail, flag;
}trie[]; void init()
{
while(!q.empty()) q.pop();
for(int i=; i<maxm; i++)
{
mem(trie[i].next, );
trie[i].fail = trie[i].flag = ;
}
tot = ;
} void insert(char *s)
{
int n = strlen(s);
int rt = ;
for(int i=;i<n; i++)
{
int x = idx[s[i]];
if(!trie[rt].next[x])
{
trie[rt].next[x] = ++tot;
// cout<< tot <<endl;
}
rt = trie[rt].next[x];
}
trie[rt].flag = ;
} void build()
{
trie[].fail= -;
q.push();
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i=; i<; i++)
{
if(trie[u].next[i] == )
{
if(u == ) trie[u].next[i] = ;
else trie[u].next[i] = trie[trie[u].fail].next[i];
}
else
{
if(u == ) trie[trie[u].next[i]].fail = ;
else{
int v = trie[u].fail;
while(v != -)
{
if(trie[v].next[i])
{
trie[trie[u].next[i]].fail = trie[v].next[i];
trie[trie[u].next[i]].flag |= trie[trie[v].next[i]].flag;
break;
}
v = trie[v].fail;
}
if(v == -) trie[trie[u].next[i]].fail = ;
}
q.push(trie[u].next[i]);
}
}
}
} Matrix mtPow(Matrix A, int k) // 用位运算代替递归求 A^k。
{
int i;
Matrix B;
for(i = ; i <= tot; i ++)
{
B.v[i][i] = ;
}
while(k)
{
if(k & ) B = B * A;
A = A * A;
k >>= ;
}
return B;
} int m, n;
char s[];
int main()
{
init();
idx['A']=; idx['C']=; idx['T']=; idx['G']=;
scanf("%d%d", &m, &n);
rap(i, , m)
{
scanf("%s", s);
insert(s);
// cout<< 111 <<endl;
}
build();
Matrix A;
// for(int i=0; i<=tot; i++) mat[i][i] = 1;
for(int i=; i<=tot; i++)
{
if(trie[i].flag) continue;
for(int j=; j<; j++)
{
if(trie[trie[i].next[j]].flag) continue;
++A.v[i][trie[i].next[j]];
}
}
A = mtPow(A, n); LL ret = ;
for(int i=; i<=tot; i++)
{
ret = (ret + A.v[][i]) % MOD;
// cout<< ans <<endl;
}
printf("%lld\n", ret); return ;
}

DNA Sequence POJ - 2778 (ac自动机 + 快速幂)的更多相关文章

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

  2. DNA Sequence POJ - 2778 AC 自动机 矩阵乘法

    定义重载运算的时候一定要将矩阵初始化,因为这个调了一上午...... Code: #include<cstdio> #include<algorithm> #include&l ...

  3. DNA Sequence - POJ 2778(AC自动机+矩阵乘法)

    题目大意:DNA序列是有 ATGC 组成的,现在知道一些动物的遗传片段有害的,那么如果给出这些有害的片段,能否求出来所有长度为 N 的基因中有多少是不包含这些有害片段的.   分析:也是断断续续做了一 ...

  4. POJ 2778 DNA Sequence ( Trie图、矩阵快速幂 )

    题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 分析: 我们先分析Tire 图的结构 : Trie图是在AC自动机的原型上增添边使得状态可以快速转移,标记危 ...

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

    题目链接:https://vjudge.net/problem/POJ-2778 题意:输入n和m表示n个病毒,和一个长为m的字符串,里面只可以有'A','C','G','T' 这四个字符,现在问这个 ...

  6. POJ 2778 (AC自动机+矩阵乘法)

    POJ 2778 DNA Sequence Problem : 给m个只含有(A,G,C,T)的模式串(m <= 10, len <=10), 询问所有长度为n的只含有(A,G,C,T)的 ...

  7. poj 2778 AC自己主动机 + 矩阵高速幂

    // poj 2778 AC自己主动机 + 矩阵高速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自 ...

  8. POJ 3691 DNA repair (DP+AC自动机)

    DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4815   Accepted: 2237 Descri ...

  9. hdu 2243 考研路茫茫——单词情结 AC自动机 矩阵幂次求和

    题目链接 题意 给定\(N\)个词根,每个长度不超过\(5\). 问长度不超过\(L(L\lt 2^{31})\),只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个? 思路 状态(AC自动 ...

随机推荐

  1. 【转载】GitHub详解

    原文:GitHub详解 GitHub详解 GitHub 是一个共享虚拟主机服务,用于存放使用Git版本控制的软件代码和内容项目.它由GitHub公司(曾称Logical Awesome)的开发者Chr ...

  2. 【LG5019】[NOIP2018]道路铺设

    [LG5019][NOIP2018]道路铺设 题面 洛谷 题解 \(NOIP\) 抄 \(NOIP\)差评 设当前做到了位置\(i\) 且\(h_i\) \(-\) \(h_i\)\(_+\)\(_1 ...

  3. 1178: [Apio2009]CONVENTION会议中心

    1178: [Apio2009]CONVENTION会议中心 https://lydsy.com/JudgeOnline/problem.php?id=1178 分析: set+倍增. 首先把所有有包 ...

  4. Yii2 Gridview 动态显示行或列和action列

    我们知道Yii中的GridView组件是非常好用的. 某些情况要动态显示某列,这时候就要用到visible属性 'propString' => ['attribute' => 'prope ...

  5. 【MongoDB安装】MongoDB在centos linux平台安装

    参考:http://www.runoob.com/mongodb/mongodb-linux-install.html 一..下载安装包 下载方式: 1.登录官网download,然后通过xftp传到 ...

  6. python开源IP代理池--IPProxys

    今天博客开始继续更新,谢谢大家对我的关注和支持.这几天一直是在写一个ip代理池的开源项目.通过前几篇的博客,我们可以了解到突破反爬虫机制的一个重要举措就是代理ip.拥有庞大稳定的ip代理,在爬虫工作中 ...

  7. Python小白学习之函数装饰器

    装饰器 2018-10-25 13:49:37 装饰器从字面意思就是用来装饰的,在函数可以理解为:在函数中,我们不想影响原来的函数功能,又想给函数添加新的功能,这时候我们就用到了装饰器. 一般函数操作 ...

  8. EOJ3650 转机折扣(26进制,字符串)

    题面 看成26进制,把较小的那个字符串加1 strcmp(s1,s2)s1和s2有大小时,不一定都是返回1或者-1.....这个地方wa了好几次没有发现 #include<bits/stdc++ ...

  9. Eclipse与MySQL数据库连接步骤

    将Eclipse与数据库进行连接的步骤: 1. 下载并配置MySQL 2. 为新建的项目配置mysql的jar包(jdbc和connection的配置) a) 可直接引用外部文件(不建议做,这样项目一 ...

  10. Ubuntu设置DNS服务

    有时候安装完Ubuntu系统,源换好好还是不能更新,软件也不能下, 配置好IP,ping 1.1.1.1是通的,ping 域名就不通了,这是没有DNS解析域名的结果 一.Server版: 对于Ubun ...