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. pycharm 对代码做静态检查

    对于下面这种情况,java c这些提前编译的语言,不给你运行机会就立马报错了,但对于动态语言运行之后才能报错,用运行的方法来检查代码错误是在是太坑了,这是py对比静态语言的巨大劣势,尤其是代码文件多行 ...

  2. [SLAM] Little about SLAM

    Books from Zhihu: 幽默一把 看完Gonzalez:嗯,好像很好玩的样子,我也来搞一搞.看完Price:什么鬼,怎么这么多公式,公式看不懂肿么破.看完Szeliski:原来用一千页的书 ...

  3. sql server 存储过程基础知识

    转自家园大哥博文http://www.cnblogs.com/jiajiayuan/archive/2011/06/15/2081201.html 什么是存储过程呢?存储过程就是作为可执行对象存放在数 ...

  4. C++ mysql 乱码

    C++读mysql数据库中的中文显示出来的是乱码 在连接到数据库后加上这么一句 mysql_query(pMYSQL, "SET NAMES GB2312"); 或者 mysql_ ...

  5. 标签a点击以后,5秒内禁止点击,5秒后激活

    方法1:利用bootstrap里面的类disabled,禁止链接 <a href='javascript:onHref()' id="test">点击</a> ...

  6. Ansible 远程执行脚本

    1. 先在服务端创建一个 shell 脚本 [root@localhost ~]$ cat /tmp/test.sh #!/bin/bash echo "hello world" ...

  7. .net页面生命周期【转】

    .Net 页面生命周期IIS 所收到的对某 Microsoft ASP.NET 页面的每个请求都被移交给 ASP.NET HTTP 管线.HTTP 管线由一系列托管对象组成,这些对象按顺序处理该请求, ...

  8. thinkphp3.2 实现上一篇和下一篇

    现在在做一个能够在内容页点击上一篇可以看到上一篇,点击下一篇可以看到下一篇. 首先http://www.mmkb.com/zhendao/index/news_show?code=98 现在code= ...

  9. C++ #include—尖括号和双引号的区别

    如果你还看一些别的C++教程,那么你可能很早就发现了,有些书上的#include命令写作#include <文件名>,但有时候又会出现#include "文件名".你会 ...

  10. LeetCode 41 First Missing Positive(找到数组中第一个丢失的正数)

    题目链接: https://leetcode.com/problems/first-missing-positive/?tab=Description   给出一个未排序的数组,求出第一个丢失的正数. ...