DNA Sequence
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 19991   Accepted: 7603

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

Source

题意:

给定m个致病基因序列。问长度为n的DNA序列中有多少个是没有这些序列的。

思路:

这道题用到AC自动机的状态转移的性质了。

当我建好了状态图之后,在某一个状态a时,我可以知道他可以到达的所有状态。Trie树上的一个节点就是一个状态。

初始矩阵mat[i][j]表示的是从状态i走一步到状态j有几种可能。使用矩阵快速幂,对这个矩阵做n次幂,就可以得到每个两个状态之间走n次总共有多少方案。

对于一个长为n的串,没有任何一个致病基因序列,那么所有致病基因转移过去的状态都不能算进去。

我们给每一个致病基因做一个危险标记,同时要注意所有fail可以到达的节点如果是danger的,他自己也要变成danger

因为这段致病基因作为后缀出现在这个串中了。

 #include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
//#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f int m, n;
const int maxn = ;
const int maxlen = 2e6 + ; struct Matrix
{
unsigned long long mat[][];
int n;
Matrix(){}
Matrix(int _n)
{
n=_n;
for(int i=;i<n;i++)
for(int j=;j<n;j++)
mat[i][j] = ;
}
Matrix operator *(const Matrix &b)const
{
Matrix ret = Matrix(n);
for(int i=;i<n;i++)
for(int j=;j<n;j++)
for(int k=;k<n;k++)
ret.mat[i][j]+=mat[i][k]*b.mat[k][j] % ;
return ret;
}
void print()
{
for(int i = ; i < n; i++){
for(int j = ; j < n; j++){
printf("%d ", mat[i][j]);
}
printf("\n");
}
}
}; unsigned long long pow_m(unsigned long long a, int n)
{
unsigned long long ret = ;
unsigned long long tmp = a;
while(n){
if(n & )ret *= tmp;
tmp *= tmp;
n >>= ;
}
return ret;
} Matrix pow_M(Matrix a, int n)
{
Matrix ret = Matrix(a.n);
for(int i = ; i < a.n; i++){
ret.mat[i][i] = ;
}
Matrix tmp = a;
//cout<<a.n<<endl;
while(n){
if(n & )ret = ret * tmp;
tmp = tmp * tmp;
n >>= ;
//ret.print();
//cout<<endl;
}
return ret;
} struct tree{
int fail;
int son[];
bool danger;
}AC[maxlen];
int tot = , id[];
char s[]; void build(char s[])
{
int len = strlen(s);
int now = ;
for(int i = ; i < len; i++){
int x = id[s[i]];
if(AC[now].son[x] == ){
AC[now].son[x] = ++tot;
}
now = AC[now].son[x];
}
AC[now].danger = true;
} void get_fail()
{
queue<int>que;
for(int i = ; i < ; i++){
if(AC[].son[i] != ){
AC[AC[].son[i]].fail = ;
que.push(AC[].son[i]);
}
}
while(!que.empty()){
int u = que.front();
que.pop();
for(int i = ; i < ; i++){
if(AC[u].son[i] != ){
AC[AC[u].son[i]].fail = AC[AC[u].fail].son[i];
que.push(AC[u].son[i]);
}
else{
AC[u].son[i] = AC[AC[u].fail].son[i];
}
int x = AC[AC[u].son[i]].fail;
if(AC[x].danger){
AC[AC[u].son[i]].danger = true;
}
}
}
} /*int AC_query(char s[])
{
int len = strlen(s);
int now = 0, cnt = 0;
for(int i = 0; i < len; i++){
int x = id[s[i]];
now = AC[now].son[x];
for(int t = now; t; t = AC[t].fail){
if(!AC[t].vis && AC[t].ed != 0){
cnt++;
AC[t].vis = true;
}
}
}
return cnt;
}*/ Matrix getMatrix()
{
Matrix ret = Matrix(tot + );
//int now = 0;
for(int i = ; i < tot + ; i++){
if(AC[i].danger)continue;
for(int j = ; j < ; j++){
if(AC[AC[i].son[j]].danger == false){
ret.mat[i][AC[i].son[j]]++;
}
}
}
for(int i = ; i < tot + ; i++){
ret.mat[i][tot] = ;
}
return ret;
} int main()
{
id['A'] = ;id['T'] = ;id['C'] = ;id['G'] = ;
//cout<<1<<endl;
while(~scanf("%d%d", &m, &n)){
for(int i = ; i <= tot; i++){
AC[i].fail = ;
AC[i].danger = false;
for(int j = ; j < ; j++){
AC[i].son[j] = ;
}
}
tot = ;
for(int i = ; i <= m; i++){
scanf("%s", s);
build(s);
}
AC[].fail = ;
get_fail();
Matrix mmm = Matrix(tot + );
//int now = 0;
for(int i = ; i < tot + ; i++){
if(AC[i].danger)continue;
for(int j = ; j < ; j++){
if(AC[AC[i].son[j]].danger == false){
mmm.mat[i][AC[i].son[j]]++;
}
}
} mmm = pow_M(mmm, n);
unsigned long long res = ;
for(int i = ; i < mmm.n; i++){
res = (res + mmm.mat[][i]) % ;
} printf("%lld\n", res);
}
//getchar();
return ;
}

poj2778 DNA Sequence【AC自动机】【矩阵快速幂】的更多相关文章

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

    题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. go 类型转换

    https://studygolang.com/articles/3400 https://studygolang.com/articles/6633

  2. 关于redis连接池

    1.redis-py不需要显式使用连接池. 在幕后,redispy使用一个连接池来管理与Redis服务器的连接.默认情况下,每个Redis实例将依次创建自己的连接池.您可以通过将已创建的连接池实例传递 ...

  3. Simply Syntax(思维)

    Simply Syntax Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5551   Accepted: 2481 Des ...

  4. easyui datagrid 单元格编辑(cell editing)

    demo中有row editing 项目中发现个cell editing,但是有bug,修改好了 主要实现功能:单击数据表格单元格,编辑单元格数据 js代码如下: $.extend($.fn.data ...

  5. Shiro集成Spring

    本篇博客主要讲述的是两者的集成.不涉及到各自的详细细节和功能. 因为官方给出的文档不够具体,对新手而言通过官方文档还不可以非常快的搭建出SpringShiro的webproject.本博客将通过实际的 ...

  6. 5 -- Hibernate的基本用法 --1 3 流行的ORM框架简介

    ⊙ JPA : JPA本身只是一种ORM规范,并不是ORM产品.它是Java EE规范制定者向开源世界学习的结果.JPA实体与Hibernate PO十分相似,甚至JPA实体完全可作为Hibernat ...

  7. WPF导航总结

    使用导航的目的是从一个页面进入到另一个页面.无论是预先决定的线性顺序(向导)还是基于层次的用户驱动程序(大部分网站的形式),或者动态生成的路径,主要有3种方法实现:调用Navigate方法,使用Hyp ...

  8. Python easyGUI 登录框 非空验证

    import easygui as g msg='欢迎注册' title='注册' fieldNames=['*用户名','*密码','*重复密码','真实姓名','手机号','QQ','e-mail ...

  9. 【内网渗透笔记】Windows2008 R2搭建域控制器

    0x00 前言 将网络中的多台计算机逻辑上组织到一起,进行集中管理,这种区别于工作组的逻辑环境叫做域(domain).域是日常计算机管理的一种很有效手段,因此,域控制器自然而然就在成域环境中最重要的角 ...

  10. 使用 Splash

    Splash 简介与安装 Splash Lua 脚本 Splash 对象属性 Splash 对象方法 Splash API 调用 Splash 负载均衡