POJ 2778 DNA Sequence —— (AC自动机+矩阵快速幂)
距离上次做AC自动机有很久了=。=,以前这题的思路死活看不懂,现在还是觉得很好理解的。
思路参见:http://blog.csdn.net/morgan_xww/article/details/7834801#。
我用cnt=1表示这个节点是危险的,然后再匹配fail指针的时候,如果一个节点的前缀是危险的,那么这个节点也是危险的,这么维护即可。
顺便一提,我以前的AC自动机模板是没有build过程中失配时的nxt指针的(以前是在match的过程中体现),但是失败时候需要的nxt指针又是很好用的,因此以后的模板中在build中新增这个内容(其实上次的AC自动机DP中就已经有了)。
另外两点可能不是很重要的是:1.我的矩阵模板统一是从1开始的,而这里有0节点;2.在结构体内似乎不能直接初始化字符串= =。
代码如下(我的代码跑的有点慢。。):
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
const int MAX_Tot = + ;
const int mod = ; int m,n; void add(int &a,int b)
{
a += b;
if(a < ) a += mod;
a %= mod;
} struct matrix
{
int e[MAX_Tot][MAX_Tot],n,m;
matrix() {}
matrix(int _n,int _m): n(_n),m(_m) {memset(e,,sizeof(e));}
matrix operator * (const matrix &temp)const
{
matrix ret = matrix(n,temp.m);
for(int i=;i<=ret.n;i++)
{
for(int j=;j<=ret.m;j++)
{
for(int k=;k<=m;k++)
{
add(ret.e[i][j],1LL*e[i][k]*temp.e[k][j]%mod);
}
}
}
return ret;
}
matrix operator + (const matrix &temp)const
{
matrix ret = matrix(n,m);
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
add(ret.e[i][j],(e[i][j]+temp.e[i][j])%mod);
}
}
return ret;
}
void getE()
{
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
e[i][j] = i==j?:;
}
}
}
}; matrix qpow(matrix temp,int x)
{
int sz = temp.n;
matrix base = matrix(sz,sz);
base.getE();
while(x)
{
if(x & ) base = base * temp;
x >>= ;
temp = temp * temp;
}
return base;
} char way[] = {'A','T','C','G'};
struct Aho
{
struct state
{
int nxt[];
int fail,cnt;
}stateTable[MAX_Tot]; int find(char c) {for(int i=;i<;i++) if(c == way[i]) return i;} int size; queue<int> que; void init()
{
while(que.size()) que.pop();
for(int i=;i<MAX_Tot;i++)
{
memset(stateTable[i].nxt,,sizeof(stateTable[i].nxt));
stateTable[i].fail = stateTable[i].cnt = ;
}
size = ;
} void insert(char *s)
{
int n = strlen(s);
int now = ;
for(int i=;i<n;i++)
{
char c = s[i];
int to = find(c);
if(!stateTable[now].nxt[to])
stateTable[now].nxt[to] = size++;
now = stateTable[now].nxt[to];
}
stateTable[now].cnt = ;
} void build()
{
stateTable[].fail = -;
que.push(); while(que.size())
{
int u = que.front();que.pop();
for(int i=;i<;i++)
{
if(stateTable[u].nxt[i])
{
if(u == ) stateTable[stateTable[u].nxt[i]].fail = ;
else
{
int v = stateTable[u].fail;
while(v != -)
{
if(stateTable[v].nxt[i])
{
stateTable[stateTable[u].nxt[i]].fail = stateTable[v].nxt[i];
// 在匹配fail指针的时候顺便更新cnt
if(stateTable[stateTable[stateTable[u].nxt[i]].fail].cnt == )
stateTable[stateTable[u].nxt[i]].cnt = ;
break;
}
v = stateTable[v].fail;
}
if(v == -) stateTable[stateTable[u].nxt[i]].fail = ;
}
que.push(stateTable[u].nxt[i]);
}
/*****建立自动机nxt指针*****/
else
{
if(u == ) stateTable[u].nxt[i] = ;
else
{
int p = stateTable[u].fail;
while(p != - && stateTable[p].nxt[i] == ) p = stateTable[p].fail;
if(p == -) stateTable[u].nxt[i] = ;
else stateTable[u].nxt[i] = stateTable[p].nxt[i];
}
}
/*****建立自动机nxt指针*****/
}
}
} matrix build_matrix()
{
matrix ans = matrix(size,size);
for(int i=;i<size;i++)
{
for(int j=;j<;j++)
{
if(!stateTable[i].cnt && !stateTable[stateTable[i].nxt[j]].cnt)
ans.e[i+][stateTable[i].nxt[j]+]++;
}
}
return ans;
}
}aho; int main()
{
while(scanf("%d%d",&m,&n) == )
{
aho.init();
char s[];
for(int i=;i<=m;i++)
{
scanf("%s",s);
aho.insert(s);
}
aho.build();
matrix p = aho.build_matrix();
p = qpow(p,n);
int ans = ;
for(int i=;i<=aho.size;i++) add(ans, p.e[][i]);
printf("%d\n",ans);
}
return ;
}
POJ 2778 DNA Sequence —— (AC自动机+矩阵快速幂)的更多相关文章
- poj 2778 DNA Sequence ac自动机+矩阵快速幂
		
链接:http://poj.org/problem?id=2778 题意:给定不超过10串,每串长度不超过10的灾难基因:问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中? DN ...
 - POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂
		
这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的t ...
 - POJ 2778 DNA Sequence (AC自动机,矩阵乘法)
		
题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种. 思路:用AC自动机,利用AC自动机上的节点做矩阵乘法. #include<iostream> #includ ...
 - [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 ...
 - POJ 2778 DNA Sequence ( AC自动机、Trie图、矩阵快速幂、DP )
		
题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 分析 : 这题搞了我真特么久啊,首先你需要知道的前置技能包括 AC自动机.构建Trie图.矩阵快速幂,其中矩 ...
 - POJ 2778 DNA Sequence (AC自动机+DP+矩阵)
		
题意:给定一些串,然后让你构造出一个长度为 m 的串,并且不包含以上串,问你有多少个. 析:很明显,如果 m 小的话 ,直接可以用DP来解决,但是 m 太大了,我们可以认为是在AC自动机图中,根据离散 ...
 - poj2778DNA Sequence (AC自动机+矩阵快速幂)
		
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud DNA Sequence Time Limit: 1000MS Memory ...
 - 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自动机
		
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11860 Accepted: 4527 Des ...
 
随机推荐
- Asp.Net Core 轻松学系列-3项目目录和文件作用介绍
			
目录 前言 结语 前言 上一章介绍了 Asp.Net Core 的前世今生,并创建了一个控制台项目编译并运行成功,本章的内容介绍 .NETCore 的各种常用命令.Asp.Net Core M ...
 - 解决IE8中select下拉列表文字上下不居中的问题
			
对IE8及以下的浏览器设置padding属性,其他浏览器则设置line-height 属性
 - JS 学习书籍电子版PDF下载
			
JavaScript权威指南(第6版)(中文版) 链接:https://pan.baidu.com/s/1H1v77UY-yh7oDxonRjd0GA 提取码:r3pu JavaScript DOM编 ...
 - numpy相关使用
			
相关学习资料 : numpy中文网 https://www.numpy.org.cn/ 1 numpy索引区间为左闭右开,第一个索引能取到,第二个索引取不到 索引内可加步长 如 import nump ...
 - crunch离线密码生成
			
Crunch是一种创建密码字典工具,按照指定的规则生成密码字典,可以灵活的制定自己的字典文件. 一.Crunch为kali自带工具之一在kali环境下进行,默认基于26个小写英文字母. 语法:cru ...
 - JdbcTemplate批量插入数据
			
运行环境:SpringBoot,注入JdbcTemplate @Autowired private JdbcTemplate jdbcTemplate; 1.单表批量插入数据 @Test public ...
 - 【Distributed】分布式锁
			
一.概述 1.1 分布式解决的核心思路 1.2 分布式锁一般有三种实现方式 二.基于Redis的分布式锁 2.1 使用常用命令 2.2 实现思路 2.3 核心代码 Maven依赖信息 LockRedi ...
 - springboot的简单热部署
			
最近开始学习使用springboot但springboot项目和之前的ssm等各种框架项目有所不同,本身集成了很多繁琐的东西,但 一些小功能还需自己配置.下面开始配置热部署. 首先当然是导入热部署的依 ...
 - c# 构造函数举例
 - L1与L2正则化
			
目录 过拟合 结构风险最小化原理 正则化 L2正则化 L1正则化 L1与L2正则化 参考链接 过拟合 机器学习中,如果参数过多.模型过于复杂,容易造成过拟合. 结构风险最小化原理 在经验风险最小化(训 ...