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. [数字dp] hdu 3271 SNIBB

    意甲冠军:有两个查询: q=1.在[x,y]间隔,兑换b十进制,数字和m多少个月. q=2.在[x,y]间隔,兑换b十进制,数字是m第一k的数目是多少(十进制),没有输出由给定的主题. 思维: 和比特 ...

  2. 安装在谷歌axure小工具

    下载插件 第一步 第二步 第三步 第四步 版权声明:本文博客原创文章.博客,未经同意,不得转载.

  3. This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.

    Attempt to load Oracle client libraries threw BadImageFormatException. This problem will occur when ...

  4. WPF分辨率适应

    double x = SystemParameters.WorkArea.Width;//得到屏幕工作区域宽度 double y = SystemParameters.WorkArea.Height; ...

  5. JS实时检测文本框内容长度

    通过js代码实时监测,文本框内容的变化以及长度,下图是一个实际使用场景. HTML部分: <input id="Text1" type="text" on ...

  6. TThreadList Demo

    type TForm1 = class(TForm) Button1: TButton; Button3: TButton; ListBox1: TListBox; Button2: TButton; ...

  7. 2018-4-25-- 2.在sublime3里安装git插件并连接GitHub

    1.配置全局参数 Git的主要配置包括用户名.邮箱的设置.以及生成SSH密钥公钥等. 首先运行一下的命令设置git提交代码时自己的用户信息. 2.在sublime3里使用时需要配置push.defau ...

  8. SQL 时间格式化函数发布

    SQL 时间格式化函数,有时候因某种需要需要格式化成需要的时间格式,需要的朋友可以收藏下,以备后用. SQL Server里面可能经常会用到的日期格式转换方法: sql server使用convert ...

  9. 【备忘】WPF基础

    XAML 为了避免生成用户界面(GUI)的代码和基于用户操作执行的代码混合在一起. 名称空间 值得注意的名称空间: xmlns="http://schemas.microsoft.com/w ...

  10. 制作Qt应用程序的插件(使用QtPlugin),对比DLL它是全平台通用的

    在Qt下,插件有两种形式,一种是用于QtCreator下,扩展IDE功能.另一种是用于扩展开发者的应用.本文要讲的是后者. 定义一个纯虚类作为插件接口 #include <QtPlugin> ...