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

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; typedef long long LL;
const int N = 500, CH = 4;
struct Trie{
Trie *next[CH];
Trie *fail;
int cnt, id;
}tree[N]; int Hash[128];
bool flag[1008];
int chi[108][4]; const LL MOD = 100000;
int num;
struct Mat{
LL mat[108][108]; Mat(){
for(int i = 0; i <= num; i++){
for(int j = 0; j <= num; j++){
mat[i][j] = 0;
}
}
}
Mat operator*(const Mat &b){
Mat res;
for(int i = 0;i <= num; i++){
for(int j = 0; j <= num; j++){
for(int k = 0; k <= num; k++){
if(mat[i][k] == 0 || b.mat[k][j] == 0){
continue;
}
res.mat[i][j] += (mat[i][k] * b.mat[k][j])%MOD;
}
res.mat[i][j] %= MOD;
}
}
return res;
}
Mat operator^(LL k){
Mat res;
Mat a = *this;
for(int i = 0; i <= num; i++){
res.mat[i][i] = 1;
}
while(k){
if(k%2){
res = res * a;
}
a = a * a;
k /= 2;;
}
return res;
}
}; class ACauto{
public:
int nxt;
Trie *root; ACauto(){
root = &tree[0];
nxt=0;
memset(&tree[0], 0, sizeof(Trie));
} void insert(char *s){
Trie *p = root;
for(int i = 0; s[i]; i++){
int c = Hash[s[i]];
if(!p -> next[c]){
memset(&tree[++nxt], 0, sizeof(Trie));
p -> next[c] = &tree[nxt];
p -> next[c] -> id = nxt;
}
p = p -> next[c];
}
p -> cnt++;
flag[p -> id] = 1;
} void build(){
queue<Trie *> q;
q.push(root);
root -> fail = NULL;
while(!q.empty()){
Trie *cur = q.front();
q.pop();
//是否为终止结点
if(cur ->fail && cur != root && flag[cur->fail->id]){
flag[cur->id] = 1;
} for(int i = 0; i < CH; i++){
Trie *son = cur -> next[i];
Trie *tp = (cur == root)? root: cur -> fail->next[i];
if(son == NULL){
cur -> next[i] = tp;
}else{
son -> fail = tp;
q.push(son);
}
son = cur -> next[i];
//儿子节点
chi[cur -> id][i] = son -> id;
}
}
} }; char str[1008];
int main(){
Hash['A'] = 0;
Hash['C'] = 1;
Hash['G'] = 2;
Hash['T'] = 3;
int m;
LL n;
while(~scanf("%d %I64d", &m, &n)){
ACauto ac;
memset(flag, 0, sizeof(flag));
memset(chi, -1, sizeof(chi));
for(int i = 0; i < m; i++){
scanf("%s", str);
ac.insert(str);
}
ac.build();
num = ac.nxt;
Mat mt;
//mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数
for(int i = 0; i <= num ; i++){
for(int j = 0; j < 4; j++){
if(flag[chi[i][j]] == 0){
mt.mat[i][chi[i][j]]++;
}
}
}
mt = mt ^ n;
LL res = 0;
for(int i = 0; i <= num; i++){
res = (res + mt.mat[0][i]) % MOD;
}
printf("%I64d\n", res); }
return 0;
}

  

POJ2778 DNA Sequence(AC自动机 矩阵)的更多相关文章

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

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

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

  3. POJ2278 DNA Sequence —— AC自动机 + 矩阵优化

    题目链接:https://vjudge.net/problem/POJ-2778 DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Tota ...

  4. 【距离GDOI:128天】【POJ2778】DNA Sequence(AC自动机+矩阵加速)

    已经128天了?怎么觉得上次倒计时150天的日子还很近啊 ....好吧为了把AC自动机搞透我也是蛮拼的..把1030和这道题对比了无数遍...最终结论是...无视时间复杂度,1030可以用这种写法解. ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. C/C++相对论——C++中为什么要使用异常?

    C++中为什么要使用异常? 很多人也许知道C++中的异常机制,很多人也许不知道.很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它. 对于C语言,使用正常的if-else即是 ...

  2. ganglia及ganglia-api相关介绍

    1, ganglia的安装: http://blog.topspeedsnail.com/archives/3049 2, ganglia-api项目地址 https://github.com/gua ...

  3. 【GoLang】GO语言系列--002.GO语言基础

    002.GO语言基础 1 参考资料 1.1 http://www.cnblogs.com/vimsk/archive/2012/11/03/2736179.html 1.2 https://githu ...

  4. bitnami-redmine 安装与插件使用

    bitnami-redmine 公司要进行敏捷开发管理,选择Redmine作为管理工具. 而Redmine本身的需要的环境比较麻烦,需要安装mysql,ruby,redmine,apach. Bitn ...

  5. 利用闪回查看Oracle表历史时刻数据

    利用闪回查看Oracle表历史时刻数据 1.查看表历史时刻数据 select * from tab_test AS OF TIMESTAMP to_timestamp('20140917 10:00: ...

  6. oracle:安装笔记

  7. Minimum Adjustment Cost

    Given an integer array, adjust each integers so that the difference of every adjacent integers are n ...

  8. poj 1326

    http://poj.org/problem?id=1326 一个模拟的水题 题意就是要你算飞行的英里数. F代表头等舱,为实际飞行的英里数的2倍. B为商务舱,为实际飞行的英里数的1.5倍. Y为经 ...

  9. DELPHI控件:DBLookupComboBOX组件的使用方法

    在许多数据表中,数据是以代码方式存放的,如在班级编码数据表tB03(表5.5)中,系部字段TB0309采用编码方式存放,系部真实名称则存放在系部编码表TB06.使用代码的好处是,用户可在编码表TB06 ...

  10. ItemsSource绑定后ScrollViewer不复位

    ItemsSource绑定后ScrollViewer不复位 ItemsSource绑定后ScrollViewer不复位,有的时候我们需要这一效果,但大多数情况下我们是想让它复位的. 在WPF中也有这个 ...