poj2778

题意

构造只包含 \(A, T, C, G\) 的字符串,且满足不出现指定的一些字符串,问长度为 \(n\) 的字符串有多少种 ?

分析

AC 自动机 + 矩阵快速幂的神题 ,知识点很多。。。

AC 自动机为了给不同的状态之间建边,矩阵快速幂是为了加速状态转移。

比如说一共有 \(5\) 个状态,我要从 状态 \(0\) 转移到 状态 \(4\) ,从 \(0\) 出发,可以先转移到 \(0\) 再转移到 \(4\) ,也可以先转移到 \(1\) 再转移到 \(4\) ,后面类似。

建一个邻接矩阵,\(mat[i][j]\) 表示 \(i\) 转移到 \(j\) 的方案数,想象一下矩阵相乘的情况,\(mat[0][4]\) 的计算过程,神奇。。。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int MAXN = 105;
const int MOD = 1e5;
int n, m;
struct Matrix {
ll mat[MAXN][MAXN];
void init() {
memset(mat, 0, sizeof mat);
}
};
Matrix operator*(Matrix A, Matrix B) {
Matrix C;
C.init();
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
for(int k = 0; k < n; k++) {
C.mat[i][j] = (C.mat[i][j] + A.mat[i][k] * B.mat[k][j]) % MOD;
}
}
}
return C;
}
Matrix operator^(Matrix A, int x) {
Matrix B;
B.init();
for(int i = 0; i < n; i++) B.mat[i][i] = 1;
while(x) {
if(x & 1) B = B * A;
A = A * A;
x >>= 1;
}
return B;
}
struct Trie {
int id[100];
int root, L, nxt[MAXN][4], val[MAXN], fail[MAXN];
int newnode() {
for(int i = 0; i < 4; i++) {
nxt[L][i] = -1;
}
return L++;
}
void init() {
id['A'] = 0; id['T'] = 1; id['C'] = 2; id['G'] = 3;
L = 0;
root = newnode();
memset(val, 0, sizeof val);
}
void insert(char s[15]) {
int len = strlen(s);
int now = root;
for(int i = 0; i < len; i++) {
int d = id[s[i]];
if(nxt[now][d] == -1) nxt[now][d] = newnode();
now = nxt[now][d];
}
val[now] = 1;
}
void build() {
queue<int> Q;
for(int i = 0; i < 4; i++) {
if(nxt[root][i] == -1) nxt[root][i] = root;
else {
fail[nxt[root][i]] = root;
Q.push(nxt[root][i]);
}
}
while(!Q.empty()) {
int now = Q.front(); Q.pop();
if(val[fail[now]]) val[now] = 1;
for(int i = 0; i < 4; i++) {
if(nxt[now][i] == -1) nxt[now][i] = nxt[fail[now]][i];
else {
fail[nxt[now][i]] = nxt[fail[now]][i];
Q.push(nxt[now][i]);
}
}
}
}
Matrix buildMatrix() {
Matrix A; A.init();
for(int i = 0; i < L; i++) {
for(int j = 0; j < 4; j++) {
if(!val[i] && !val[nxt[i][j]]) {
A.mat[i][nxt[i][j]]++;
}
}
}
return A;
}
}trie;
int main() {
trie.init();
int k;
scanf("%d%d", &m, &k);
for(int i = 0; i < m; i++) {
char s[15];
scanf("%s", s);
trie.insert(s);
}
trie.build();
Matrix A = trie.buildMatrix();
n = trie.L;
A = A ^ k;
int ans = 0;
for(int i = 0; i < n; i++) {
ans = (ans + A.mat[0][i]) % MOD;
}
printf("%d\n", ans);
return 0;
}

poj2778(AC 自动机)的更多相关文章

  1. poj2778 ac自动机+矩阵快速幂

    给m个子串,求长度为n的不包含子串的母串数,最直接的应该是暴搜,肯定tle,考虑用ac自动机 将子串建成字典树,通过next表来构造矩阵,然后用矩阵快速幂求长度为n的数量 邻接矩阵https://we ...

  2. poj2778 AC自动机

    以下内容均为转载,,只有代码是自己写的=-= http://blog.csdn.net/morgan_xww/article/details/7834801   转载地址 博主写的很好 ------- ...

  3. 【POJ2778】DNA Sequence(AC自动机,DP)

    题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATC ...

  4. 【POJ2778】AC自动机+矩阵乘法

    DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...

  5. POJ2778 DNA Sequence(AC自动机 矩阵)

    先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数. #include<cstdio& ...

  6. POJ2778 DNA Sequence(AC自动机+矩阵快速幂)

    题目给m个病毒串,问不包含病毒串的长度n的DNA片段有几个. 感觉这题好神,看了好久的题解. 所有病毒串构造一个AC自动机,这个AC自动机可以看作一张有向图,图上的每个顶点就是Trie树上的结点,每个 ...

  7. poj2778(AC自动机+矩阵快速幂)

    题意:给你n个字符串,问你长度为m的字符串且字符串中不含有那n个子串的字符串的数量 解题思路:这道题一开始就不太懂,还以为是组合数学的题目,后面看了别人的博客,才知道这是属于AC自动机的另一种用法,是 ...

  8. 【POJ2778】DNA Sequence 【AC自动机,dp,矩阵快速幂】

    题意 题目给出m(m<=10)个仅仅由A,T,C,G组成的单词(单词长度不超过10),然后给出一个整数n(n<=2000000000),问你用这四个字母组成一个长度为n的长文本,有多少种组 ...

  9. poj2778 DNA Sequence【AC自动机】【矩阵快速幂】

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19991   Accepted: 7603 Des ...

随机推荐

  1. [bzoj2893] 集合计数

    Description 一个有N个元素的集合有2^N 个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得 它们的交集的元素个数为K,求取法的方案数,答案模100000000 ...

  2. VB托盘图标不响应WM_MOUSEMOVE的原因及解决方法

    文章参考地址:http://blog.csdn.net/txh0001/article/details/38265895:http://bbs.csdn.net/topics/330106030 网上 ...

  3. 安徽师大附中%你赛day9 T2 富 解题报告

    富 题目背景 出于某些原因, 苟先生在追杀富先生. 题目描述 富先生所在的地方是一个\(n\times m\)的网格,苟先生排出了他的狼狗大军,共有\(k\)条狗,第\(i\)条狗所在的位置为\((x ...

  4. Treap 模板

    感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系 推荐博客:http://memphis.is-programmer.com/post ...

  5. POJ3660:Cow Contest(Floyd传递闭包)

    Cow Contest Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16941   Accepted: 9447 题目链接 ...

  6. Java中Class<T>与Class<?>的区别

    E - Element (在集合中使用,因为集合中存放的是元素) T - Type(Java 类) K - Key(键) V - Value(值) N - Number(数值类型) ? - 表示不确定 ...

  7. jquery中:input和input的区别

    :input表示选择表单中的input,select,textarea,button元素, input仅仅选择input元素. <button>和<input type=" ...

  8. 使用vue开发webApp,安卓手机自带回退键的问题解决

    首先,我先为大家说明,为什么我要写这篇随笔: 因为我们写的webapp,在安卓手机上,按一次回退键,就会退出app,回到桌面,而不是像原生app一样,会有一个提示,例如,“再按一次退出应用”的这种提示 ...

  9. LOJ tangjz的背包

    题目大意 有 \(n\) 个物品, 第 \(i\) 个物品的体积为 \(i\) 令 \(f(x)\) 为 选择 \(m\) 个物品, 体积和为 \(x\) 的方案数 令 \(V = \sum_{i=1 ...

  10. 编写类du命令Python脚本

    #!/usr/bin/env python #_*_ coding:utf-8 _*_ #计算整个目录的大小,脚本接受-H参数,来加上适当的单位 #功能像du看齐 import os,sys from ...