【POJ2778】DNA Sequence 【AC自动机,dp,矩阵快速幂】
题意
题目给出m(m<=10)个仅仅由A,T,C,G组成的单词(单词长度不超过10),然后给出一个整数n(n<=2000000000),问你用这四个字母组成一个长度为n的长文本,有多少种组成方法可以使得它不含任何一个给出的单词。
分析
当时一看以为是跟训练指南上(UVA11468)一样的题,感觉只有四个字母并且单词数量和长度也比较小,但是一看给出的n有点懵逼。如果再按照书上建立AC自动机以后直接跑DP的方法肯定是不行了。然后我们就要用到,递推利器,矩阵快速幂。
我们还是按照套路先把AC自动机建出来,然后将每个单词结点设为非法结点,题目变成在AC自动机中走n步不通过非法结点的方案数。然后设f[i][j]是当前在结点i,已经走了j步,且未走过非法结点的方案数。然后怎么转移呢?
f[i][j]=A(0,i)*f[0][j-1]+A(1,i)*f[1][j-1]+...+A(sz-1,i)f[sz-1][j-1]。其中A(i,j)的含义就是从i到j有几条直接连接的边。那么将这个dp方程拆开来看
f0[i]=A(0,0)*f[0][i-1]+A(1,0)*f[1][i-1]+....+A(sz-1,0)*fsz-1[i-1]
f1[i]=A(0,1)*f[0][i-1]+A(1,1)*f[1][i-1]+....+A(sz-1,1)*fsz-1[i-1]
.
.
fsz-1[i]=A(0,sz-1)*f[0][i-1]+A(1,sz-1)*f[1][i-1]+...+A(sz-1,sz-1)*fsz-1[i-1]
然后根据这个我们就很好建立转移矩阵
*
(第一次学会用公式编辑器不过好像还是贼丑)
然后建立这个大的转移矩阵,矩阵的(i,j)为结点i到结点j的直接路径的条数,然后跑一个矩阵快速幂。
最后把从0到sz-1结点的f(n)的值全部加起来就是答案了。
对了这个题需要用long long
下面是代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map> using namespace std;
const int maxnode=;
const int MOD=;
map<char,int>M;
struct AC_Automata{
int ch[maxnode][],f[maxnode],last[maxnode],val[maxnode],match[maxnode];
int sz;
int idx(char c){
return M[c];
}
void init(){
sz=;
memset(ch[],,sizeof(ch[]));
memset(match,,sizeof(match));
val[]=;
}
void insert(char *s){
int n=strlen(s),u=;
for(int i=;i<n;i++){
int c=idx(s[i]);
if(!ch[u][c]){
ch[u][c]=sz;
memset(ch[sz],,sizeof(ch[sz]));
val[sz++]=;
}
u=ch[u][c];
}
val[u]=;
match[u]=;
}
void getFail(){
queue<int>q;
last[]=f[]=;
for(int i=;i<;i++){
int u=ch[][i];
if(u){
q.push(u);
f[u]=last[u]=;
}
}
while(!q.empty()){
int r=q.front();q.pop();
for(int i=;i<;i++){
int u=ch[r][i];
if(!u){
ch[r][i]=ch[f[r]][i];
continue;
}
q.push(u);
int v=f[r];
while(v&&!ch[v][i])v=f[v];
f[u]=ch[v][i];
match[u]|=match[f[u]];
}
}
}
}ac;
const int maxN=;
struct Matrix{
long long a[maxN][maxN];
void init(){
memset(a,,sizeof(a));
for(int i=;i<ac.sz;i++)
a[i][i]=;
}
};
Matrix mul(Matrix a,Matrix b){
Matrix res;
for(int i=;i<ac.sz;i++){
for(int j=;j<ac.sz;j++){
res.a[i][j]=;
for(int k=;k<ac.sz;k++){
res.a[i][j]+=a.a[i][k]*b.a[k][j];
res.a[i][j]%=MOD;
}
}
}
return res;
}
Matrix qpow(Matrix a,int k){
Matrix res;
res.init();
while(k){
if(k%)res=mul(res,a);
a=mul(a,a);
k/=;
}
return res;
}
int n,m;
char s[]; int main(){
M['A']=,M['C']=,M['T']=,M['G']=;
ac.init();
scanf("%d%d",&m,&n);
for(int i=;i<=m;i++){
scanf("%s",s);
ac.insert(s);
}
ac.getFail();
Matrix A;
for(int i=;i<ac.sz;i++){
if(!ac.match[i])
for(int j=;j<;j++){
int u=ac.ch[i][j];
if(!ac.match[u])
A.a[i][u]++;
}
}
/*for(int i=0;i<ac.sz;i++){
for(int j=0;j<ac.sz;j++){
printf("%d ",A.a[i][j]);
}
printf("\n");
}*/ Matrix S;
S.a[][]=;
Matrix ANS;
ANS=qpow(A,n);
ANS=mul(S,ANS);
long long ans=;
for(int i=;i<=ac.sz;i++)
ans+=ANS.a[][i];
printf("%d\n",ans%MOD);
return ;
}
【POJ2778】DNA Sequence 【AC自动机,dp,矩阵快速幂】的更多相关文章
- [poj2778 DNA Sequence]AC自动机,矩阵快速幂
题意:给一些字符串的集合S和整数n,求满足 长度为n 只含charset = {'A'.'T‘.'G'.'C'}包含的字符 不包含S中任一字符串 的字符串的种类数. 思路:首先对S建立ac自动机,考虑 ...
- 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂
[题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...
- POJ 2778 DNA Sequence (AC自动机+DP+矩阵)
题意:给定一些串,然后让你构造出一个长度为 m 的串,并且不包含以上串,问你有多少个. 析:很明显,如果 m 小的话 ,直接可以用DP来解决,但是 m 太大了,我们可以认为是在AC自动机图中,根据离散 ...
- poj 2778 DNA Sequence AC自动机DP 矩阵优化
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11860 Accepted: 4527 Des ...
- Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂)
Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂) 题目链接 题解: 多串匹配问题,很容易想到是AC自动机 先构建忌讳词语的AC自动机,构建时顺便记录一下这个点以及它的所有后 ...
- 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂
[题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...
- BZOJ2553 Beijing2011禁忌(AC自动机+动态规划+矩阵快速幂+概率期望)
考虑对一个串如何分割能取得最大值.那么这是一个经典的线段覆盖问题,显然每次取右端点尽量靠前的串.于是可以把串放在AC自动机上跑,找到一个合法串后就记录并跳到根. 然后考虑dp.设f[i][j]表示前i ...
- POJ 2778 DNA Sequence ( Trie图、矩阵快速幂 )
题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 分析: 我们先分析Tire 图的结构 : Trie图是在AC自动机的原型上增添边使得状态可以快速转移,标记危 ...
- [poj2778]DNA Sequence(AC自动机+矩阵快速幂)
题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...
- 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 ...
随机推荐
- 阻塞队列 BlockingQueue 详解
转自:https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247487078&idx=2&sn=315f39b6d53 ...
- CH5702 Count The Repetitions
题意 5702 Count The Repetitions 0x50「动态规划」例题 描述 定义 conn(s,n) 为 n 个字符串 s 首尾相接形成的字符串,例如: conn("abc& ...
- spotlight工具监控oracle
spotlight工具版本Version: 5.0.1.1022 安装步骤 安装完成 安装之后,桌面上会生成如下图标 双机此图标,输入License 输入激活码 点击close,再次查看 建立连接,监 ...
- k8s中yaml文件pod的语法(转)
kubernetes yaml格式的Pod配置文件 # yaml格式的pod定义文件完整内容: apiVersion: v1 #必选,版本号,例如v1 kind: Pod #必选,Pod metada ...
- visio画图有感
昨天在和一个同事看流程图,在我还在考虑图的含义时他说这个图太乱了,如果要团队成员看也会很费劲,并找出觉得画的好的案例. 对比两个图我发现了一个最大的差别是好的图形状都是水平或垂直对齐的,连接线也都是水 ...
- 第3章 Vim使用笔记
3.1 vi使用map自定义快捷方式 [想要永久保存定义的快捷键在-/.vimrc[进入root后才能看到~/.vimrc文件]中编辑保存即可!] set nu 输入下列命令[:map <spe ...
- kafka原理和实践(四)spring-kafka消费者源码
系列目录 kafka原理和实践(一)原理:10分钟入门 kafka原理和实践(二)spring-kafka简单实践 kafka原理和实践(三)spring-kafka生产者源码 kafka原理和实践( ...
- Redis和Memcache区别,优缺点对比
1. Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等. 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供li ...
- react-native 获取组件的宽度和高度
react-native 获取组件的尺寸有两种方式,第一种方式使用元素自身的onLayout属性去获取,但是这种方式有一个局限性,就是只有在初次渲染的时候才会触发这个函数,而且此种方法获取的是组件相对 ...
- VUE图片懒加载-vue lazyload插件的简单使用
序:vue项目时候,我们要对图片进行懒加载处理,这个开发项目中就不需要自己去写了,因为比较方便使用vue lazyload进行处理,高效率开发 一. vue lazyload插件: 插件地址:http ...