题目链接:http://poj.org/problem?id=2778

题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列。(仅含A,T,C,G四个字符)

思路:Trie图的状态转移,用矩阵mat[i][j]来表示从结点i到j只走一步有几种走法,那么mat的n次幂就表示从结点i到j走n步有几种走法,题目要求解的就是从头节点走n步且不包含危险结点的走法。

mat = mat^n   ans = (mat[0][0] + mat[0][1] + ... + mat[0][num]) num为结点个数

code:

 #include <cstdio>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
const int KIND = ;
const int MAXN = ;
const int MOD = ;
typedef long long LL; struct Trie
{
int next[MAXN][KIND], fail[MAXN];
bool isExit[MAXN];
int root, L;
map<char, int> mp;
LL mat[MAXN][MAXN];
LL ret[MAXN][MAXN];
LL tmp[MAXN][MAXN];
int create()
{
for (int i = ; i < KIND; ++i)
next[L][i] = -;
isExit[L++] = false;
return L - ;
}
void init()
{
L = ;
root = create();
mp['A'] = ;
mp['C'] = ;
mp['G'] = ;
mp['T'] = ;
memset(mat, , sizeof(mat));
memset(ret, , sizeof(ret));
}
void insert(char str[])
{
int now = root;
int len = strlen(str);
for (int i = ; i < len; ++i)
{
if (- == next[now][mp[str[i]]])
next[now][mp[str[i]]] = create();
now = next[now][mp[str[i]]];
}
isExit[now] = true;
}
void build()
{
queue<int>Q;
for (int i = ; i < KIND; ++i)
{
if (- == next[root][i])
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while (!Q.empty())
{
int now = Q.front();
Q.pop();
if (isExit[fail[now]])
isExit[now] = true;
for (int i = ; i < KIND; ++i)
{
if (- == next[now][i])
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
void getMatrix()
{
for (int i = ; i < L; ++i)
{
for (int j = ; j < KIND; ++j)
{
if (!isExit[next[i][j]])
++mat[i][next[i][j]];
}
}
}
void matrixMul(LL mat1[MAXN][MAXN], LL mat2[MAXN][MAXN])
{
LL mat3[MAXN][MAXN];
for (int i = ; i < L; ++i)
{
for (int j = ; j < L; ++j)
{
mat3[i][j] = ;
for (int k = ; k < L; ++k)
mat3[i][j] = (mat3[i][j] + mat1[i][k] * mat2[k][j]) % MOD;
}
}
memcpy(mat1, mat3, sizeof(mat3));
}
void matrixQuickMod(LL n)
{
getMatrix();
for (int i = ; i < L; ++i)
{
ret[i][i] = ;
for (int j = ; j < L; ++j)
tmp[i][j] = mat[i][j];
}
while (n)
{
if (n & ) matrixMul(ret, tmp);
matrixMul(tmp, tmp);
n >>= ;
}
}
};
Trie ac;
char str[];
int main()
{
int m;
LL n;
while (scanf("%d %lld", &m, &n) != EOF)
{
ac.init();
for (int i = ; i < m; ++i)
{
scanf("%s", str);
ac.insert(str);
}
ac.build();
ac.matrixQuickMod(n);
int ans = ;
for (int i = ; i < ac.L; ++i)
ans = (ans + ac.ret[][i]) % MOD;
printf("%d\n", ans);
}
return ;
}

POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)的更多相关文章

  1. poj 2778 DNA Sequence ac自动机+矩阵快速幂

    链接:http://poj.org/problem?id=2778 题意:给定不超过10串,每串长度不超过10的灾难基因:问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中? DN ...

  2. POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂

    这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的t ...

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

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

  4. [poj2778]DNA Sequence(AC自动机+矩阵快速幂)

    题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...

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

  6. POJ 2778 DNA Sequence ( AC自动机、Trie图、矩阵快速幂、DP )

    题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 分析 : 这题搞了我真特么久啊,首先你需要知道的前置技能包括 AC自动机.构建Trie图.矩阵快速幂,其中矩 ...

  7. POJ 2778 DNA Sequence (AC自动机+DP+矩阵)

    题意:给定一些串,然后让你构造出一个长度为 m 的串,并且不包含以上串,问你有多少个. 析:很明显,如果 m 小的话 ,直接可以用DP来解决,但是 m 太大了,我们可以认为是在AC自动机图中,根据离散 ...

  8. poj2778DNA Sequence (AC自动机+矩阵快速幂)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud DNA Sequence Time Limit: 1000MS   Memory ...

  9. poj 2778 DNA Sequence AC自动机DP 矩阵优化

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11860   Accepted: 4527 Des ...

  10. poj 2778 DNA Sequence AC自动机

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11860   Accepted: 4527 Des ...

随机推荐

  1. 今天起改用mac的marsedit写博

    最近一直使用mac来工作,所以写博也相应改为marsedit. 初步感觉还是不错的,越来越发现mac其实也适合在工作中使用,生活上当然不在话下. 从高富帅的x220t变成屌丝的macbook小白(升级 ...

  2. 如何让多个不同版本的jquery库共存

    问题描述:公司的登录接口使用的是jquery1.4.2,因为我要使用一个jquery.pagination的分页控件(jquery1.7.2).如果我使用了1.7.2,登录接口会有问题. <sc ...

  3. [置顶] Android系统移植与调试之------->如何修改Android设备状态条上音量加减键在横竖屏的时候的切换与显示

    这两天由于一个客户的要求,将MID竖屏时候的状态条上的音量键去掉.所以尝试修改了一下,成功了,分享一下经验. 先看一下修改后的效果图,如下所示 . 横屏的时候:有音量加减键 竖屏的时候:音量加减键被去 ...

  4. label 标签

    <label> 标签为 input 元素定义标注内容 label 元素不会向用户呈现任何特殊效果.不过,它为鼠标用户改进了可用性.如果您在 label 元素内点击文本,就会触发此控件.就是 ...

  5. 理解session机制

    理解session机制 session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息. 当程序需要为某个客户端的请求创建一个session的时候,服务器首 ...

  6. 统计分析SQL Server Profiler 跟踪的SQL

    --跟踪文件读入到表中分析 SELECT * INTO ZGSJY FROM fn_trace_gettable('E:\wxxcdbprofiler.trc', default); --某时间内,最 ...

  7. prototype演变

    setp1 var Person = function () {}; //构造器 var p = new Person(); setp1 演变: var Person = function () {} ...

  8. 微信支付 v 3.3.6

    文字说明: 前提:注册.申请服务号,开通微信支付. 涉及到的参数:AppId.AppSecret.原始ID(自动回复).mch_id(商户号).Key(商户密钥:自己设定.) 统一规范: 要求 认证方 ...

  9. JSP标签库

    step1: 定义一个标签处理类:改类必须实现SimpleTag接口,在实际中是拓展它的子类SimpleTagSupport.复写doTag方法 public class MyTag extends ...

  10. Struts学习之手动验证

    * 首先要从页面中获取对应的标签name属性的值,在动作类action中声明同名的属性,提供get和set方法    * 要继承ActionSupport类或者实现Validateable接口     ...