http://poj.org/problem?id=2778

题意:有m个病毒DNA,问构造一个长度为n的不带病毒DNA的字符串可以有多少种。

思路:看到这题有点懵,想了挺久题解的思路。

使用AC自动机判断总共有哪些状态,和哪些状态是不可取的。

然后构造出矩阵mat,mat[i][j]代表从状态i走到状态j走一步可以有多少种走法,然后走n步就是mat[i][j]^n(就像你走第一步可以有2种走法,走第二步可以有2^2种走法,走第三步可以有2^3种走法一样的道理(一开始还想不懂))。

在AC自动机判断状态不可取的时候,不但是插入的串末尾不可取,而且如果fail指针指向的状态是不可取的,那么当前的状态也是不可取的!因为fail指针指向的是当前匹配了的串的最长后缀,那么当前匹配了的串必定包含了fail指针指向的串(病毒串)。

还参考了很多数据==。

 #include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define N 105
#define TOL 4
#define MOD 100000
typedef long long LL; int sz; typedef struct Node {
Node *next[TOL];
Node *fail; int flag, id;
Node () {
for(int i = ; i < TOL; i++) next[i] = NULL;
fail = NULL; flag = ; id = sz++;
}
} node; class Matrix { public: LL mat[N][N]; void init() { memset(mat, , sizeof(mat)); } void identity() { memset(mat, , sizeof(mat)); for(int i = ; i < sz; i++) mat[i][i] = ; } static void print(Matrix now) {
printf("sz : %d\n", sz);
for(int i = ; i < sz; i++) {
for(int j = ; j < sz; j++) {
printf("%d ", now.mat[i][j]);
}
puts("");
}
} friend Matrix operator * (const Matrix &a, const Matrix &b) {
Matrix c; c.init();
for(int i = ; i < sz; i++) {
for(int k = ; k < sz; k++) {
for(int j = ; j < sz; j++) {
c.mat[i][k] = c.mat[i][k] + a.mat[i][j] * b.mat[j][k];
}
c.mat[i][k] %= MOD; // 如果放在里面会TLE
}
}
return c;
} friend Matrix operator ^ (Matrix a, int k) {
Matrix b; b.identity();
while(k) {
if(k & ) b = b * a;
a = a * a;
k >>= ;
}
return b;
} void solve(Matrix now, int n) {
now = now ^ n;
int sum = ;
for(int i = ; i < sz; i++) { sum = (sum + now.mat[][i]); if(sum >= MOD) sum -= MOD; }
printf("%d\n", sum % MOD);
}
}; class AC_DFA { private: node* root;
vector<node*> dic; public: AC_DFA() {
dic.clear();
root = new node();
sz = ; dic.push_back(root);
} ~AC_DFA() {
for(int i = ; i < sz; i++) delete dic[i];
} int get(char c) {
if(c == 'A') return ;
if(c == 'C') return ;
if(c == 'G') return ;
return ;
} void insert(char *s) {
node* now = root;
int len = strlen(s);
for(int i = ; i < len; i++) {
int c = get(s[i]);
if(now->next[c] == NULL) now->next[c] = new node(), dic.push_back(now->next[c]);
now = now->next[c];
}
now->flag = ;
} void build() {
queue<node*> que;
root->fail = NULL;
que.push(root);
while(!que.empty()) {
node* now = que.front(); que.pop();
for(int i = ; i < TOL; i++) {
if(now->next[i]) {
node* p = now->fail;
while(p && p->next[i] == NULL) p = p->fail;
// 如果指向的fail是病毒,那么now->next[i]也是带病毒的,因为指向的fail是其最大后缀
if(p) now->next[i]->fail = p->next[i], now->next[i]->flag |= p->next[i]->flag;
else now->next[i]->fail = root;
que.push(now->next[i]);
} else {
if(now == root) now->next[i] = root;
else now->next[i] = now->fail->next[i];
}
}
}
} Matrix buildMatrix() {
Matrix a; a.init();
for(int i = ; i < dic.size(); i++) {
for(int j = ; j < TOL; j++) {
if(dic[i]->next[j]->flag == ) {
int tmp = dic[i]->next[j]->id;
a.mat[i][tmp]++;
}
}
}
return a;
}
}; int main() {
int m, n;
scanf("%d%d", &m, &n);
char s[N];
AC_DFA ac;
for(int i = ; i < m; i++)
scanf("%s", s), ac.insert(s);
ac.build();
Matrix now = ac.buildMatrix();
now.solve(now, n);
return ;
} /*
4 3
AT
AC
AG
AA
10 100
AGAGAGT
CGTATTG
AAAATTTCGC
GCGTA
TCGA
AATTGGA
TAGATAGC
AGCGTATT
TTCGA
TACGTATTG
3 10
AT
GATC
TGAC
48233
*/

POJ 2778:DNA Sequence(AC自动机构造矩阵)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. poj 2778 DNA Sequence AC自动机

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

  7. POJ 2778 DNA Sequence (AC自己主动机 + dp)

    DNA Sequence 题意:DNA的序列由ACTG四个字母组成,如今给定m个不可行的序列.问随机构成的长度为n的序列中.有多少种序列是可行的(仅仅要包括一个不可行序列便不可行).个数非常大.对10 ...

  8. POJ 2778 DNA Sequence ( Trie图、矩阵快速幂 )

    题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 分析: 我们先分析Tire 图的结构 : Trie图是在AC自动机的原型上增添边使得状态可以快速转移,标记危 ...

  9. [poj2778 DNA Sequence]AC自动机,矩阵快速幂

    题意:给一些字符串的集合S和整数n,求满足 长度为n 只含charset = {'A'.'T‘.'G'.'C'}包含的字符 不包含S中任一字符串 的字符串的种类数. 思路:首先对S建立ac自动机,考虑 ...

  10. 2018 焦作网络赛 L Poor God Water ( AC自动机构造矩阵、BM求线性递推、手动构造矩阵、矩阵快速幂 )

    题目链接 题意 : 实际上可以转化一下题意 要求求出用三个不同元素的字符集例如 { 'A' .'B' .'C' } 构造出长度为 n 且不包含 AAA.BBB CCC.ACB BCA.CAC CBC ...

随机推荐

  1. Codeforces Round #263 (Div. 2) proA

    称号: A. Appleman and Easy Task time limit per test 1 second memory limit per test 256 megabytes input ...

  2. WPF里的一些Effect特效

    原文:WPF里的一些Effect特效 Blend的特效都在Microsoft.Expression.Media.Effects里,用之前添加一下引用. 可以在前台选中对象后直接点击Effect新建一种 ...

  3. WebAPI Delete方法报错405 Method Not Allowed

    .net framework 在Web.config文件中添加如下配置: <system.webServer> <modules runAllManagedModulesForAll ...

  4. 如何自定义WPF项目的Main函数

    原文:如何自定义WPF项目的Main函数 与Winform项目不同,WPF项目的Main函数在项目生成的时候,系统自动在后台为我们生成.根据项目生成方式的不同,其文件位于obj/Debug/App.g ...

  5. WPF 拖动多个文件到窗体 添加文件信息

    将Window的AllowDrop属性设置为true window添加Drop事件 private void Window_Drop(object sender, DragEventArgs e) { ...

  6. 将自定义控件加载到RichTextbox并进行交互

    先前遇到一个问题,将自定义控件加载到RichTextbox后,无法触发自定义控件的各种事件,最终找到解决办法:设置RichTextbox的IsDocumentEnabled="True&qu ...

  7. WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化)

    原文:WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化) 注释直接写在代码里了   不太理解意思的 可以先去看看我上一篇  WPF ScrollViewer(滚动条)  自定 ...

  8. 怎么给开源项目提PR?

    1. fork 你要的项目 2. 下载到本地 相关步骤如下 在你需要的文件夹下面,右键 git bash 命令,打开 git 命令框 执行如下指令可将项目代码下载到当前目录 ~~~ git clone ...

  9. ARC forbids explicit message send of'retain'解决办法

    项目中导入一些开源的类库,里面会爆出一些ARC forbids explicit message send of'retain' 这种问题 解决方法: 点击项目Target -> 找到" ...

  10. SQL Server 事务复制分发到订阅同步慢

    原文:SQL Server 事务复制分发到订阅同步慢 最近发现有一个发布经常出现问题,每几天就出错不同步,提示要求初始化.重新调整同步后,复制还是很慢!每天白天未分发的命令就达五六百万条!要解决慢的问 ...