DNA Sequence - POJ 2778(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自动机+矩阵乘法)的更多相关文章
- DNA Sequence POJ - 2778 AC 自动机 矩阵乘法
定义重载运算的时候一定要将矩阵初始化,因为这个调了一上午...... Code: #include<cstdio> #include<algorithm> #include&l ...
- 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 ...
- POJ 2778 (AC自动机+矩阵乘法)
POJ 2778 DNA Sequence Problem : 给m个只含有(A,G,C,T)的模式串(m <= 10, len <=10), 询问所有长度为n的只含有(A,G,C,T)的 ...
- poj 2778 AC自动机+矩阵快速幂
题目链接:https://vjudge.net/problem/POJ-2778 题意:输入n和m表示n个病毒,和一个长为m的字符串,里面只可以有'A','C','G','T' 这四个字符,现在问这个 ...
- 【bzoj1444】[Jsoi2009]有趣的游戏 AC自动机+矩阵乘法
题目描述 输入 注意 是0<=P 输出 样例输入 样例输出 题解 AC自动机+矩阵乘法 先将所有字符串放到AC自动机中,求出Trie图. 然后构建邻接矩阵:如果x不是某个字符串的末位置,则x连向 ...
- POJ 2778 DNA Sequence (AC自动机,矩阵乘法)
题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种. 思路:用AC自动机,利用AC自动机上的节点做矩阵乘法. #include<iostream> #includ ...
- 【poj2778-DNA Sequence】AC自动机+矩阵乘法
题意: (只含AGCT)给定m个病毒串,让你构造一个长度为n的字符串(也只含有AGCT),问有多少种方案.n很大:1<=n<=2000000000 题解: 用病毒串建立AC自动机(num个 ...
- 【POJ2778】AC自动机+矩阵乘法
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
随机推荐
- Xcode4.4中,代码无法高亮、无法自动补全
1.代码无法高亮显示:2.代码不能自动补全,或者给出提示建议:(当然这个补全的功能我在设置当中是打开的状态)3.新建一个项目,代码还是依然没有高亮显示,但是有补全功能:4.然后我就在网络上搜索了相关的 ...
- Python:标准数据类型6种
#!/usr/bin/python3 #python的基本语法和数据类型 #python3中 一行有多个语句,用分号分割(;) print("aaa") ;print(" ...
- 通用方法解决dedecms导航调用二级、三级栏目菜单
博客之前做网站的时候经常会遇到二级菜单.三级菜单.了解dede的人都知道从5.5版本开始都有二级菜单的调用方法了,网上也有不少的教程文章.不过这个调用需要修改dede源码的二级菜单样式.个人感觉不是很 ...
- phpcms v9 get调用标签整理
常见的phpcms标签调用 1.调用本系统单条数据(调用ID为1的信息,标题长度不超过25个汉字,显示更新日期): "select * from phpcms_content where ...
- 知识库总结mysql常用cmd命令
打开命令目录 打开D盘mysql目录 d: cd D:\Ampps\mysql\bin 常用操作 将mysql目录下bin目录中的mysql.exe放到C:\WINDOWS下,可以执行以下命令 连接: ...
- Ubuntu14.02 Sublimte2安装
$sudo add-apt-repository ppa:webupd8team/sublime-text-2 $sudo apt-get update $sudo apt-get install s ...
- 简单的贴图显示shander
Shader "ztq/Diffuse" { Properties { _Color ("Main Color", Color) = ...
- coroutine协程
如果你接触过lua这种小巧的脚本语言,你就会经常接触到一个叫做协程的神奇概念.大多数脚本语言都有对协程不同程度的支持.但是大多编译语言,如C/C++,根本就不知道这样的东西存在.当然也很多人研究如何在 ...
- 开发人员应关注的20个jQuery网站/博客
http://blog.jobbole.com/1466/ 2. 10个优秀的移动Web应用开发框架 http://blog.jobbole.com/1436/ 3. 介绍jQ Mobile ht ...
- [BZOJ 3110] [Zjoi2013] K大数查询 【树套树】
题目链接: BZOJ - 3110 题目分析 这道题是一道树套树的典型题目,我们使用线段树套线段树,一层是区间线段树,一层是权值线段树.一般的思路是外层用区间线段树,内层用权值线段树,但是这样貌似会很 ...