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. .NET 上传并解析CSV文件存库

    1.前端: 放置浏览按钮 <div class="row inner_table text-center"> <input id="fileId&quo ...

  2. Entity States

    Added. The entity does not yet exist in the database. The SaveChanges method must issue an INSERT st ...

  3. WPF 过滤集合

    <Window x:Class="ViewExam.MainWindow"        xmlns="http://schemas.microsoft.com/w ...

  4. WPF Layout 系统概述——Measure

    原文:WPF Layout 系统概述--Measure 前言 在WPF/Silverlight当中,如果已经存在的Element无法满足你特殊的需求,你可能想自定义Element,那么就有可能会面临重 ...

  5. 获取bing图片并自动设置为电脑桌面背景(使用 URLDownloadToFile API函数)

    众所周知,bing搜索网站首页每日会更新一张图片,张张漂亮(额,也有一些不合我口味的),特别适合用来做电脑壁纸. 我们想要将bing网站背景图片设置为电脑桌面背景的通常做法是: 上网,搜索bing 找 ...

  6. awk积累

    1. 计算一个文本中每一列的和 [root@centos ~]# cat aaa.txt [root@centos ~]# awk 'BEGIN{a=0;b=0;c=0}{a+=$1;b+=$2;c+ ...

  7. MySql5.7.11 for Windows 安装(二)

    原文:MySql5.7.11 for Windows 安装(二) 安装之后,首先创建data文件夹(旧版本本来就有),管理员打开cmd,cd到bin文件夹,输入 mysqld –initialize- ...

  8. 卸载win10内置windows app的方法

    原文:卸载win10内置windows app的方法 2015年,微软推出了windows10操作系统,其以漂亮的界面.良好的操作方式.方便的推送升级迅速获得了好多人的好评,因此,好多同学都换了win ...

  9. 关于EF ORM 框架的使用问题

    1.无法更新 EntitySet“System_UserInfo20140218001”,因为它有一个 DefiningQuery,而 <ModificationFunctionMapping& ...

  10. js打印指定元素内容

    var v = document.createElement("div"); //向v中追加打印数据,可以将界面的元素追加进来 var h = window.open(" ...