题目大意:DNA序列是有 ATGC 组成的,现在知道一些动物的遗传片段有害的,那么如果给出这些有害的片段,能否求出来所有长度为 N 的基因中有多少是不包含这些有害片段的。
 
分析:也是断断续续做了一天,做这道题前先做一下 hdu2157 这道题,因为这道题的思路就是从它转变过来的,看明白了这个后,就需要构造一个矩阵,不过因为按照自己的想法构造的矩阵,一直WA,不明白为什么,后来发现是因为在子节点不存在时候查询后缀时候包含子节点的时候不彻底造成的,还是对AC自动机了解的不多。不过通过这题也学会了矩阵快速幂,算是不错的收获。
 
代码如下:
==========================================================================================================================
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std; const int MAXN = ;
const int MAXM = ;
const int mod = ; struct Matrix{long long edge[MAXN][MAXN];};
struct TrieNode
{
TrieNode *Fail, *next[MAXM];
int danger, Num;///节点编号,是否是危险指针
}; int GetVal(char ch)
{
if(ch == 'A')return ;
if(ch == 'T')return ;
if(ch == 'G')return ; return ;
}
void Insert(TrieNode *root, char s[], int &Num)
{
TrieNode *p = root; for(int i=; s[i]; i++)
{
int k = GetVal(s[i]); if(p->next[k] == NULL)
{
p->next[k] = new TrieNode();
p->next[k]->Num = ++Num;
}
p = p->next[k];
} p->danger = true;
}
void GetFail(TrieNode *root)
{
TrieNode *p = root, *temp;
queue<TrieNode *> Q; for(int i=; i<MAXM; i++)
{
if(p->next[i])
{
p->next[i]->Fail = root;
Q.push(p->next[i]);
}
} while(Q.size())
{
p = Q.front();
Q.pop(); for(int i=; i<MAXM; i++)if(p->next[i])
{
temp = p->Fail; while(temp != NULL)
{
if(temp->next[i] != NULL)
{
p->next[i]->Fail = temp->next[i];
///如果这个后缀是危险节点的话,那么向下传递一下
p->next[i]->danger |= temp->next[i]->danger; break;
} temp = temp->Fail;
} if(temp == NULL)
p->next[i]->Fail = root; Q.push(p->next[i]);
}
} root->Fail = root;
}
void GetMatrix(TrieNode *root, Matrix &Map)
{
TrieNode *p = root, *temp; if(p->danger)return ; for(int i=; i<MAXM; i++)
{
if(p->next[i])
GetMatrix(p->next[i], Map); temp = p;
///当p->next[i] 不存在时,访问它的后缀Fail,直到根节点停止
while(temp->Num != && !temp->next[i])
temp = temp->Fail; if(!temp->next[i])
{///如果在前后缀没有找到,那么就走向根节点处
Map.edge[p->Num][]++;
continue;
}
///如果这个点是危险节点
if(temp->next[i]->danger)continue; Map.edge[p->Num][temp->next[i]->Num]++;
}
}
void Mul(Matrix a, Matrix b, Matrix &ans, int len)
{
memset(ans.edge, , sizeof(ans.edge)); for(int i=; i<=len; i++)
for(int j=; j<=len; j++)
for(int k=; k<=len; k++)
{
ans.edge[i][j] += a.edge[i][k] * b.edge[k][j];
ans.edge[i][j] %= mod;
}
}
void QuickPow(Matrix Map, long long k, Matrix &ans, int len)
{
memset(ans.edge, , sizeof(ans.edge)); for(int i=; i<=len; i++)
ans.edge[i][i] = ; while(k)
{
if(k & )
Mul(ans, Map, ans, len);
Mul(Map, Map, Map, len); k /= ;
}
} void FreeTrie(TrieNode *root)
{
for(int i=; i<MAXM; i++)
{
if(root->next[i])
FreeTrie(root->next[i]);
} free(root);
} int main()
{
long long M, K; while(scanf("%lld%lld", &M, &K) != EOF)
{
char s[MAXN];
int num = ;
TrieNode *root = new TrieNode(); while(M--)
{
scanf("%s", s);
Insert(root, s, num);
} GetFail(root); Matrix Map, ans; memset(Map.edge, , sizeof(Map.edge)); GetMatrix(root, Map);
QuickPow(Map, K, ans, num); long long sum=; for(int i=; i<=num; i++)
{
sum = (sum + ans.edge[][i]) % mod;
} printf("%lld\n", sum); FreeTrie(root);
} return ;
}

DNA Sequence - POJ 2778(AC自动机+矩阵乘法)的更多相关文章

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

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

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

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

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

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

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

  5. 【bzoj1444】[Jsoi2009]有趣的游戏 AC自动机+矩阵乘法

    题目描述 输入 注意 是0<=P 输出 样例输入 样例输出 题解 AC自动机+矩阵乘法 先将所有字符串放到AC自动机中,求出Trie图. 然后构建邻接矩阵:如果x不是某个字符串的末位置,则x连向 ...

  6. POJ 2778 DNA Sequence (AC自动机,矩阵乘法)

    题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种. 思路:用AC自动机,利用AC自动机上的节点做矩阵乘法. #include<iostream> #includ ...

  7. 【poj2778-DNA Sequence】AC自动机+矩阵乘法

    题意: (只含AGCT)给定m个病毒串,让你构造一个长度为n的字符串(也只含有AGCT),问有多少种方案.n很大:1<=n<=2000000000 题解: 用病毒串建立AC自动机(num个 ...

  8. 【POJ2778】AC自动机+矩阵乘法

    DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...

  9. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

随机推荐

  1. sp_addlinkedserver的一些操作

    sp_addlinkedserver 创建一个链接的服务器,使其允许对分布式的.针对 OLE DB 数据源的异类查询进行访问.在使用 sp_addlinkedserver 创建链接的服务器之后,此服务 ...

  2. idea配置tomcat.md

    [toc] 1.打开Edit Configurations,可以通过万能搜索快速进入!!! 2.添加服务器,在左上角找到Tomcat并添加 3.配置发布路径,Server标签页中填写完名称和路径,在D ...

  3. 一种实现C++反射功能的想法(三)

    如何实现类型名跟类型的对应, 我们很容易想到map, 没错, 就是使用map实现的. std::map<std::string, .....>, 等下, 第二部分该填什么类型, 一个函数指 ...

  4. SGU 113.Nearly prime numbers

    水一个代码: #include <iostream> using namespace std; int n, a; bool ok; bool prime (int x) { ; i * ...

  5. javascript——面向对象程序设计(4)

    <script type="text/javascript"> //1.继承 //2.原型链 //3.借用构造函数 //4.组合继承 //5.原型式继承 //6.寄生式 ...

  6. 不学就吃亏的underscorejs类库学习示例 ——(集合篇)

    underscorejs是一个很不错的类库,我的很多项目都引用了这个类库,的确可以带来很多方便. 记得我当初学的时候,看underscorejs的api是看的一知半解的,甚至不明白api里的conte ...

  7. Python Tutorial 学习(三)--An Informal Introduction to Python

    3.1. 将Python用作计算器 3.1.1. Numbers 数 作为一个计算器,python支持简单的操作, '+','-','*','/'地球人都知道的加减乘除. ()可以用来改变优先级,同数 ...

  8. C语言学习笔记(二):指针的用法

    与其说指针是一种工具,不如先说指针是一种数据类型. -------------------------------------------------------------华丽的分割线------- ...

  9. ssh远程登录Ubuntu报错:Permission denied, please try again.

    ssh到server上的时候密码是对的但是报如下信息:# ssh 172.16.81.221root@172.16.81.221's password:Permission denied, pleas ...

  10. SSH三种框架及表示层、业务层和持久层的理解

    Struts(表示层)+Spring(业务层)+Hibernate(持久层) SSH:Struts(表示层)+Spring(业务层)+Hibernate(持久层) Struts:Struts是一个表示 ...