【poj2778-DNA Sequence】AC自动机+矩阵乘法
题意:
(只含AGCT)给定m个病毒串,让你构造一个长度为n的字符串(也只含有AGCT),问有多少种方案。
n很大:1<=n<=2000000000
题解:
用病毒串建立AC自动机(num个节点),然后构建一个num*num的矩阵表示节点i走一步到j有多少种方案。注意:根节点也要算。
原理:原本是在AC自动机上不断地走,但不能走到病毒末端。该矩阵每格(i,j)表示i走一步到j有多少种方案,n次方就是i走n步到j有多少种方案。
最后把矩阵[0][i]全部加起来,就是从0出发走n步的全部方案。
为什么可以只用AC自动机上的节点?因为走其他节点就相当于回到根节点,假设给定一个新构造的串要你判断是不是有病毒串,也不需要除了病毒串以外的节点来判断。
注意要用longlong。
代码如下
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std; const int N=,M=,Mod=;
typedef long long LL;
int num,n,m;
char s[];
queue<int> q;
struct node{
int bk,fail,son[];
}a[];
struct nd{
int x,y;
LL z[][];
}map; // void output(nd p)
// {
// for(int i=0;i<=p.x;i++)
// {
// for(int j=0;j<=p.y;j++)
// printf("%d ",p.z[i][j]);
// printf("\n");
// }
// printf("\n");
// } int idx(char c)
{
if(c=='A') return ;
if(c=='T') return ;
if(c=='C') return ;
if(c=='G') return ;
} void clear(int x)
{
a[x].fail=a[x].bk=;
memset(a[x].son,,sizeof(a[x].son));
} void trie(char *c)
{
int x=,l=strlen(c);
for(int i=;i<l;i++)
{
int ind=idx(c[i]);
if(!a[x].son[ind])
{
num++;
clear(num);
a[x].son[ind]=num;
}
x=a[x].son[ind];
}
a[x].bk=;
} void buildAC()
{
while(!q.empty()) q.pop();
q.push();
while(!q.empty())
{
int x=q.front();q.pop();
int fail=a[x].fail;
for(int i=;i<=;i++)
{
if(a[x].son[i])
{
int y=a[x].son[i],z=a[fail].son[i];
a[y].fail=x ? z : ;
a[y].bk|=a[z].bk;
q.push(y);
}
else a[x].son[i]=a[fail].son[i];
if(!a[a[x].son[i]].bk) map.z[x][a[x].son[i]]++;
} }
} nd multi(nd u,nd v)
{
nd ans;
ans.x=u.x;ans.y=v.y;
memset(ans.z,,sizeof(ans.z));
for(int i=;i<=ans.x;i++)
for(int j=;j<=ans.y;j++)
for(int k=;k<=ans.y;k++)
ans.z[i][j]=(ans.z[i][j]+u.z[i][k]*v.z[k][j])%Mod;
return ans;
} LL dp()
{
nd ans;
ans.x=num,ans.y=num;
memset(ans.z,,sizeof(ans.z));
for(int i=;i<=num;i++) ans.z[i][i]=;
while(n)
{
if(n&) ans=multi(ans,map);
map=multi(map,map);
n/=;
}
LL sum=;
for(int i=;i<=num;i++)
sum=(sum+ans.z[][i])%Mod;
return sum;
} int main()
{
freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
scanf("%d%d",&m,&n);
for(int i=;i<=m;i++)
{
scanf("%s",s);
trie(s);
}
map.x=num,map.y=num;
memset(map.z,,sizeof(map.z));
buildAC();
printf("%I64d\n",dp());
return ;
}
很久以前刚学打过一次,以前的代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std; const int M=;
const int MOD=(int)1e5;
char s[M];
int q[M];
long long ay[M][M],sum[M][M];
int n,m,tot,len;
struct node
{
int son[],cnt,fail,mark;
}t[M]; void floy()
{
tot=;
for(int i=;i<=M;i++)
{
t[i].cnt=;t[i].mark=;
for(int j=;j<=;j++) t[i].son[j]=;
}
memset(q,,sizeof(q));
memset(ay,,sizeof(ay));
memset(sum,,sizeof(sum));
} void read_trie()
{
tot=;
int i,j;
scanf("%d%d",&m,&n);
for(i=;i<=m;i++)
{
int x,ind;
scanf("%s",s+);
len=strlen(s+);
x=;
for(j=;j<=len;j++)
{
if(s[j]=='A') ind=;
if(s[j]=='C') ind=;
if(s[j]=='T') ind=;
if(s[j]=='G') ind=; if(!t[x].son[ind]) t[x].son[ind]=++tot;
x=t[x].son[ind];
t[x].cnt++;
if(j==len) t[x].mark=;
}
}
} void build_AC()
{
int i,j,x,y;
q[++q[]]=;
for(i=;i<=q[];i++)
{
x=q[i];
y=t[x].fail;
for(j=;j<=;j++)
{
if(t[x].son[j])
{
//t[t[x].son[j]].fail=t[y].son[j];
//while(y && !t[y].son[j]) y=t[y].fail;
t[t[x].son[j]].fail=x?t[y].son[j]:;
if(t[t[t[x].son[j]].fail].mark) t[t[x].son[j]].mark=;
q[++q[]]=t[x].son[j];
}
else t[x].son[j]=t[y].son[j];
if(!t[t[x].son[j]].mark) ++ay[x][t[x].son[j]];
}
}
} void MatrixMult(long long a[M][M],long long b[M][M])
{
int i,j,k;
long long c[M][M]={};
for(i=;i<=tot;i++)
for(j=;j<=tot;j++)
for(k=;k<=tot;k++)
c[i][j]+=a[i][k]*b[k][j];
for(i=;i<=tot;i++)
for(j=;j<=tot;j++)
a[i][j]=c[i][j]%MOD;
} long long MatrixPow(int k)
{
int i,j;
for(i=;i<=tot;i++)
for(j=;j<=tot;j++)
sum[i][j]=(i==j);
while(k)
{
if(k&) MatrixMult(sum,ay);
MatrixMult(ay,ay);
k>>=;
}
for(int i=;i<=tot;i++)
{
for(int j=;j<=tot;j++)
printf("%d ",sum[i][j]);
printf("\n");
}
long long ans=;
for(i=;i<=tot;i++) ans+=sum[][i];
return ans%MOD;
} int main()
{
freopen("a.in","r",stdin);
// freopen("b.out","w",stdout);
floy();
read_trie();
build_AC(); printf("%I64d\n",MatrixPow(n));
return ;
}
poj2778(以前的代码)
【poj2778-DNA Sequence】AC自动机+矩阵乘法的更多相关文章
- POJ 2778 DNA Sequence (AC自动机,矩阵乘法)
题意:给定n个不能出现的模式串,给定一个长度m,要求长度为m的合法串有多少种. 思路:用AC自动机,利用AC自动机上的节点做矩阵乘法. #include<iostream> #includ ...
- [poj2778]DNA Sequence(AC自动机+矩阵快速幂)
题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...
- POJ2778 DNA Sequence(AC自动机 矩阵)
先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数. #include<cstdio& ...
- 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 ...
- POJ2278 DNA Sequence —— AC自动机 + 矩阵优化
题目链接:https://vjudge.net/problem/POJ-2778 DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Tota ...
- 【距离GDOI:128天】【POJ2778】DNA Sequence(AC自动机+矩阵加速)
已经128天了?怎么觉得上次倒计时150天的日子还很近啊 ....好吧为了把AC自动机搞透我也是蛮拼的..把1030和这道题对比了无数遍...最终结论是...无视时间复杂度,1030可以用这种写法解. ...
- [poj2778 DNA Sequence]AC自动机,矩阵快速幂
题意:给一些字符串的集合S和整数n,求满足 长度为n 只含charset = {'A'.'T‘.'G'.'C'}包含的字符 不包含S中任一字符串 的字符串的种类数. 思路:首先对S建立ac自动机,考虑 ...
- poj 2778 DNA Sequence ac自动机+矩阵快速幂
链接:http://poj.org/problem?id=2778 题意:给定不超过10串,每串长度不超过10的灾难基因:问在之后给定的长度不超过2e9的基因长度中不包含灾难基因的基因有多少中? DN ...
- 【bzoj1444】[Jsoi2009]有趣的游戏 AC自动机+矩阵乘法
题目描述 输入 注意 是0<=P 输出 样例输入 样例输出 题解 AC自动机+矩阵乘法 先将所有字符串放到AC自动机中,求出Trie图. 然后构建邻接矩阵:如果x不是某个字符串的末位置,则x连向 ...
- DNA Sequence - POJ 2778(AC自动机+矩阵乘法)
题目大意:DNA序列是有 ATGC 组成的,现在知道一些动物的遗传片段有害的,那么如果给出这些有害的片段,能否求出来所有长度为 N 的基因中有多少是不包含这些有害片段的. 分析:也是断断续续做了一 ...
随机推荐
- 关于VS2010“ADO.NET Entity Data Model模板丢失或者添加失败问题
我最近在安装vs2010后,添加ADO.NET Entity 实体时发现,我的新建项里面并没有这个实体模型,后来我就在博问里面发表了问题,请求大家帮忙解决,悲剧的是少有人回应啊,呵呵,不过我还是在网上 ...
- vimium
安装在chrome上的一个插件,可以实现chrome无鼠标无键盘操作. 事实上vimium就是提供了一系列的快捷键列表,所以只要熟悉了这些快捷键就可以方便使用了. 要查看快捷键列表,打开chrome, ...
- ArcGIS Server10.2服务启动不了之http://localhost:6080/arcgis/manager无法打开之arcMap 无法打开6080admin问题解决之路
遇到的问题:在services.msc中可以正常启动arcGIS server ,但是过几秒种服务就自动关闭, 而且manager打不开, 各种方法都试过了,什么关闭杀毒软件,更改服务配置文件,更改a ...
- 评价正在使用输入法软件产品----QQ拼音输入法
评价一下大家手头正在使用输入法或者搜索类的软件产品. 我现在使用的是系统自带的QQ拼音输入法,以前使用的是搜狗拼音输入法,后来发现可能由于我的系统重装过好几次,搜狗输入法也重装了好几次,而每次都删不干 ...
- "渴了么"用户场景分析
典型用户 (1)名字:王美丽 (2)年龄:21 (3)收入:勤工助学和兼职等 (4)代表的用户在市场上的比例和重要性(比例大不等同于重要性高,如付费的用户比例较少,但是影响大,所以更重要). 作为大学 ...
- fwrite ,fprintf的作用与区别
1.概念和作用 fwrite是C语言函数,指向文件写入一个数据块,写入的是 fprintf是C/C++中的一个格式化写-库函数,其作用是格式输出到一个流/文件中:原型是int fprintf( FIL ...
- C实现面向对象封装、继承、多态
参考资料: http://blog.chinaunix.net/uid-26750235-id-3102371.html http://www.eventhelix.com/rea ...
- JS 学习笔记--3--数据类型
1.typeof 操作符 用来获取变量或者字面量的类型,也可以typeof(x);但是typeof并非内置函 数,而是一个操作符变量2.JS 一共6种类型 Undefined/Null/Boolean ...
- Spring Batch学习
今天准备研究下Spring Batch,然后看了一系列资料,如下还是比较好的教程吧. 链接: http://www.cnblogs.com/gulvzhe/archive/2011/12/20/229 ...
- idea maven添加jar包
在“项目结构“里设置 选择libaray,添加jar包