POJ2778 DNA Sequence(AC自动机 矩阵)
先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; typedef long long LL;
const int N = 500, CH = 4;
struct Trie{
Trie *next[CH];
Trie *fail;
int cnt, id;
}tree[N]; int Hash[128];
bool flag[1008];
int chi[108][4]; const LL MOD = 100000;
int num;
struct Mat{
LL mat[108][108]; Mat(){
for(int i = 0; i <= num; i++){
for(int j = 0; j <= num; j++){
mat[i][j] = 0;
}
}
}
Mat operator*(const Mat &b){
Mat res;
for(int i = 0;i <= num; i++){
for(int j = 0; j <= num; j++){
for(int k = 0; k <= num; k++){
if(mat[i][k] == 0 || b.mat[k][j] == 0){
continue;
}
res.mat[i][j] += (mat[i][k] * b.mat[k][j])%MOD;
}
res.mat[i][j] %= MOD;
}
}
return res;
}
Mat operator^(LL k){
Mat res;
Mat a = *this;
for(int i = 0; i <= num; i++){
res.mat[i][i] = 1;
}
while(k){
if(k%2){
res = res * a;
}
a = a * a;
k /= 2;;
}
return res;
}
}; class ACauto{
public:
int nxt;
Trie *root; ACauto(){
root = &tree[0];
nxt=0;
memset(&tree[0], 0, sizeof(Trie));
} void insert(char *s){
Trie *p = root;
for(int i = 0; s[i]; i++){
int c = Hash[s[i]];
if(!p -> next[c]){
memset(&tree[++nxt], 0, sizeof(Trie));
p -> next[c] = &tree[nxt];
p -> next[c] -> id = nxt;
}
p = p -> next[c];
}
p -> cnt++;
flag[p -> id] = 1;
} void build(){
queue<Trie *> q;
q.push(root);
root -> fail = NULL;
while(!q.empty()){
Trie *cur = q.front();
q.pop();
//是否为终止结点
if(cur ->fail && cur != root && flag[cur->fail->id]){
flag[cur->id] = 1;
} for(int i = 0; i < CH; i++){
Trie *son = cur -> next[i];
Trie *tp = (cur == root)? root: cur -> fail->next[i];
if(son == NULL){
cur -> next[i] = tp;
}else{
son -> fail = tp;
q.push(son);
}
son = cur -> next[i];
//儿子节点
chi[cur -> id][i] = son -> id;
}
}
} }; char str[1008];
int main(){
Hash['A'] = 0;
Hash['C'] = 1;
Hash['G'] = 2;
Hash['T'] = 3;
int m;
LL n;
while(~scanf("%d %I64d", &m, &n)){
ACauto ac;
memset(flag, 0, sizeof(flag));
memset(chi, -1, sizeof(chi));
for(int i = 0; i < m; i++){
scanf("%s", str);
ac.insert(str);
}
ac.build();
num = ac.nxt;
Mat mt;
//mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数
for(int i = 0; i <= num ; i++){
for(int j = 0; j < 4; j++){
if(flag[chi[i][j]] == 0){
mt.mat[i][chi[i][j]]++;
}
}
}
mt = mt ^ n;
LL res = 0;
for(int i = 0; i <= num; i++){
res = (res + mt.mat[0][i]) % MOD;
}
printf("%I64d\n", res); }
return 0;
}
POJ2778 DNA Sequence(AC自动机 矩阵)的更多相关文章
- [poj2778]DNA Sequence(AC自动机+矩阵快速幂)
题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...
- 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 ...
- POJ2278 DNA Sequence —— AC自动机 + 矩阵优化
题目链接:https://vjudge.net/problem/POJ-2778 DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Tota ...
- 【距离GDOI:128天】【POJ2778】DNA Sequence(AC自动机+矩阵加速)
已经128天了?怎么觉得上次倒计时150天的日子还很近啊 ....好吧为了把AC自动机搞透我也是蛮拼的..把1030和这道题对比了无数遍...最终结论是...无视时间复杂度,1030可以用这种写法解. ...
- [poj2778 DNA Sequence]AC自动机,矩阵快速幂
题意:给一些字符串的集合S和整数n,求满足 长度为n 只含charset = {'A'.'T‘.'G'.'C'}包含的字符 不包含S中任一字符串 的字符串的种类数. 思路:首先对S建立ac自动机,考虑 ...
- poj 2778 DNA Sequence ac自动机+矩阵快速幂
链接:http://poj.org/problem?id=2778 题意:给定不超过10串,每串长度不超过10的灾难基因:问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中? DN ...
- POJ 2778 DNA Sequence (AC自动机,矩阵乘法)
题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种. 思路:用AC自动机,利用AC自动机上的节点做矩阵乘法. #include<iostream> #includ ...
- poj 2778 DNA Sequence AC自动机DP 矩阵优化
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11860 Accepted: 4527 Des ...
- POJ 2778 DNA Sequence ( AC自动机、Trie图、矩阵快速幂、DP )
题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 分析 : 这题搞了我真特么久啊,首先你需要知道的前置技能包括 AC自动机.构建Trie图.矩阵快速幂,其中矩 ...
随机推荐
- 这些情况下onReume不应该是你的选择
面试Android程序员的时候问过以下几个基本问题,得到的回答经常不尽人意: 1, Activity A跳转到Activity B,Activity B完成后,Activity A要刷新一下自己的数据 ...
- 4.了解AngularJS模块和依赖注入
1.模块和依赖注入概述 1.了解模块 AngularJS模块是一种容器,把代码隔离并组织成简洁,整齐,可复用的块. 模块本身不提供直接的功能:包含其他提供功能的对象的实例:控制器,过滤器,服务,动画 ...
- c语言数据问题
变量都有作用域,链接属性,和存储类型3个属性,这三个属性决定了变量的作用域和生存期的问题 在c语言中包含4中类型, 整形 浮点型 指针 聚合类型(数组,结构体等) ------------------ ...
- idea修改默认快捷键
点击file ,选择settings. 输入keymap: 因为多数人使用的都是eclipse,比较容易上手,习惯了eclipse的键位,如 此就能更换. 也可以在对应的操作上,设置自己熟悉的键位.
- svn: E155004 'XX' is already locked
Error:svn: E155004: Run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)svn: E155 ...
- ubuntu查找软件包
sudo apt-cache search s_name
- c#.netGr idView1在div不局中
<div style="margin:0 auto;text-align:center;" >//可以用GridView剧中 <asp:GridView ID=& ...
- 【leetcode】Minimum Path Sum
Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to b ...
- NSIS脚本入门和进阶方法
NSIS(Nullsoft Scriptable Install System)是一个开源的 Windows 系统下安装程序制作程序.它提供了安装.卸载.系统设置.文件解压缩等功能.对于新手来说,它有 ...
- Unity3d 查找所选的是否引用过某资源
一.使用方式: 1.选择要被查找的资源,右键->Find Reference 2.把资源拽入Res,点Find 3.输出结果见Console //代码 using UnityEngine; us ...