POJ 2778 DNA Sequence (AC自己主动机 + dp)
DNA Sequence
(详细解释见代码)
/*
ID: wuqi9395@126.com
PROG:
LANG: C++
*/
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<fstream>
#include<cstring>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#define INF (1<<30)
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, n) for (int i = 0; i < n; i++)
#define debug puts("===============")
typedef long long ll;
using namespace std;
const int maxn = 110;
const int maxm = 110;
ll mod = 100000;
struct Matrix {
int n, m;
ll a[maxn][maxm];
void clear() {
n = m = 0;
memset(a, 0, sizeof(a));
}
Matrix operator * (const Matrix &b) const { //实现矩阵乘法
Matrix tmp;
tmp.clear();
tmp.n = n;
tmp.m = b.m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
if (!a[i][j]) continue;
for (int k = 0; k < b.m; k++)
tmp.a[i][k] += a[i][j] * b.a[j][k], tmp.a[i][k] %= mod;
} return tmp;
}
}A, res; const int maxnode = 11 * 11;
const int charset = 4;
struct ACAutomaton {
int ch[maxnode][charset];
int fail[maxnode];
int Q[maxnode];
int val[maxnode];
int sz;
int id(char ch) {
if (ch == 'A') return 0;
else if (ch == 'C') return 1;
else if (ch == 'T') return 2;
return 3;
}
void init() {
fail[0] = 0;
//for (int i = 0; i < charset; i++) ID[i] = i;
}
void reset() {
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}
void Insert(char* s, int key) {
int u = 0;
for (; *s; s++) {
int c = id(*s);
if (!ch[u][c]) {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = key;
}
void Construct () {
int *s = Q, *e = Q;
for (int i = 0; i < charset; i++) {
if (ch[0][i]) {
*e++ = ch[0][i];
fail[ch[0][i]] = 0;
}
}
while(s != e) {
int u = *s++;
if (val[fail[u]]) val[u] = 1;
for (int i = 0; i < charset; i++) {
int &v = ch[u][i];
if (v) {
*e++ = v;
fail[v] = ch[fail[u]][i];
} else {
v = ch[fail[u]][i];
}
}
}
}
/*
dp[i][j]表示长度为i。后缀为j的状态 最多就仅仅有10*10个后缀
所以可以通过dp[n][j] = a0 * dp[n-1][0] + ... + ak * dp[n - 1][k]得到状态转移的矩阵
*/
void work() {
for (int i = 0; i < sz; i++) {
for (int j = 0; j < charset; j++) {
//对于i状态,通过加入ACTG可以得到新的状态(且之前已经构造过AC自己主动机,ch[i][j]便表示新状态)
if (!val[i] && !val[ch[i][j]]) { //两个状态都必须是可行的,转化才有意义
A.a[i][ch[i][j]]++;
}
}
}
}
} AC; Matrix Matrix_pow(Matrix A, ll k, ll mod) {
res.clear();
res.n = res.m = AC.sz;
for (int i = 0; i < AC.sz; i++) res.a[i][i] = 1;
while(k) {
if (k & 1) res = res * A;
A = A * A;
k >>= 1;
}
return res;
}
int main () {
int m, n;
A.clear();
AC.init();
AC.reset();
char str[15];
scanf("%d%d", &m, &n);
for (int i = 0; i < m; i++) {
scanf("%s", str);
AC.Insert(str, 1);
}
A.n = A.m = AC.sz;
AC.Construct();
//之前的都是AC自己主动机构造部分
AC.work(); //得到状态转移的矩阵
res = Matrix_pow(A, n, mod);
int ans = 0;
rep(i, AC.sz) ans += res.a[0][i];
printf("%d\n", ans % mod);
return 0;
}
POJ 2778 DNA Sequence (AC自己主动机 + dp)的更多相关文章
- poj 1699 Best Sequence(AC自己主动机+如压力DP)
id=1699" target="_blank" style="">题目链接:poj 1699 Best Sequence 题目大意:给定N个D ...
- poj 2778 DNA Sequence AC自动机
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11860 Accepted: 4527 Des ...
- 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图.矩阵快速幂,其中矩 ...
- Hdu 2457 DNA repair (ac自己主动机+dp)
题目大意: 改动文本串的上的字符,使之不出现上面出现的串.问最少改动多少个. 思路分析: dp[i][j]表示如今 i 个字符改变成了字典树上的 j 节点. 然后顺着自己主动机一直转移方程. 注意合法 ...
- 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+矩阵)
题意:给定一些串,然后让你构造出一个长度为 m 的串,并且不包含以上串,问你有多少个. 析:很明显,如果 m 小的话 ,直接可以用DP来解决,但是 m 太大了,我们可以认为是在AC自动机图中,根据离散 ...
- POJ 3691 & HDU 2457 DNA repair (AC自己主动机,DP)
http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...
随机推荐
- Java版本的删除指定目录及子目录下名叫“xxx.txt”的所有文件
以前写过一个python版本的,但是在查找文件路径的时候出现错误,无法正确的获取到文件的路径,就造成无法删除该路径下的“xxx.txt”文件. 当时以为是windows版本系统的错误造成这个问题的,也 ...
- git指令
返回当前目录路径: $ pwd 1.1 git add git add . #将文件先暂存到staging area, stages new and modified, without deleted ...
- poj2352Stars
http://poj.org/problem?id=2352 二维逆序数 按一个数排序 转化为1维的 之前用树状数组写过 这次用线段树敲了下 #include <iostream> #in ...
- Json时间格式转换问题
很多时候在数据库中取出数据,需要用Json来接收,但是接受出来的数据竟然是:/Date(1386040883000+0800)/ 这种格式. 这个时候就需要将Json格式,转换成Javascript格 ...
- Java web 项目 tomcat部署方式.
本地做Java Web项目的时候常常会用到tomcat部署测试的问题, 这里介绍项目的部署方法: 1,配置文件的形式: 例如: 你的项目目录为:f:\workspaces\MyProject,此时使用 ...
- Android 主题动态切换框架:Prism
Prism(棱镜) 是一个全新的 Android 动态主题切换框架,虽然是头一次发布,但它所具备的基础功能已经足够强大了!本文介绍了 Prism 的各种用法,希望对你会有所帮助,你也可以对它进行扩展, ...
- MySQL table_id原理及风险分析
1. 什么是table_id MySQL binlog文件按格式分为文件头部和事件信息.文件头部占4字节,内容固定为:"\xfe\x62\x69\x6e",接下来就是各个event ...
- oracle 问题若干 提醒注意
1.Powerdesigner 里生成sql,在oracle中运行时报错:ORA-00907: 缺失右括号 解决:这样的问题很多时候是因为用了不正确的数据类型造成的.比如写作nvarchar(n),但 ...
- ZOJ 3299-Fall the Brick(线段树+离散化)
题意: n个区间 ,给出区间的左右坐标 ,区间内填满宽度为1的箱子,有m个板子给出板子的高度和左右坐标(同高度不重叠) 所有箱子从上向下落,求每块板子能接到的箱子数. 分析: 首先给的区间很大,一开始 ...
- 《零成本实现Web自动化测试--基于Selenium》 第五章 Selenium-RC
一. 简介 Selenium-RC可以适应更复杂的自动化测试需求,而不仅仅是简单的浏览器操作和线性执行.Selenium-RC能够充分利用编程语言来构建更复杂的自动化测试案例,例如读写文件.查询数据库 ...