题意

题目给出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,矩阵快速幂】的更多相关文章

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

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

  2. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  3. POJ 2778 DNA Sequence (AC自动机+DP+矩阵)

    题意:给定一些串,然后让你构造出一个长度为 m 的串,并且不包含以上串,问你有多少个. 析:很明显,如果 m 小的话 ,直接可以用DP来解决,但是 m 太大了,我们可以认为是在AC自动机图中,根据离散 ...

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

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

  5. Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂)

    Luogu-3250 [BJOI2017]魔法咒语(AC自动机,矩阵快速幂) 题目链接 题解: 多串匹配问题,很容易想到是AC自动机 先构建忌讳词语的AC自动机,构建时顺便记录一下这个点以及它的所有后 ...

  6. 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂

    [题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...

  7. BZOJ2553 Beijing2011禁忌(AC自动机+动态规划+矩阵快速幂+概率期望)

    考虑对一个串如何分割能取得最大值.那么这是一个经典的线段覆盖问题,显然每次取右端点尽量靠前的串.于是可以把串放在AC自动机上跑,找到一个合法串后就记录并跳到根. 然后考虑dp.设f[i][j]表示前i ...

  8. POJ 2778 DNA Sequence ( Trie图、矩阵快速幂 )

    题意 : 给出一些病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 分析: 我们先分析Tire 图的结构 : Trie图是在AC自动机的原型上增添边使得状态可以快速转移,标记危 ...

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

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

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

随机推荐

  1. 内存溢出eclipse启动tomcat

    1.在eclipse中的Window->preferences->Java->install jar->选择JDK,然后在点击Edit,在Default VM argument ...

  2. centos7通过yum安装mysql,并授权远程连接 【转】

    http://blog.csdn.net/u012367513/article/details/40538267 用于备忘

  3. string函数的一些实现

    /************************************************************************* > File Name: test.cpp ...

  4. Linux cp命令详解

    Linux cp命令 Linux cp命令主要用于复制文件或目录,将源文件复制至目标文件,或将多个源文件复制至目标目录 用法: cp [选项]... [-T] 源文件 目标文件 cp [选项]... ...

  5. lvs基础及部署

    LVS简介   LVS--Linux Vritual Server 即linux虚拟服务器,1998年5月由章文嵩博士开发并开源,目前全球多个国家的企业单位都在使用LVS构建集群服务.   LVS可实 ...

  6. 测试技术/网游Bug分析/单机修改 视频教程

    早期做的一些视频,测试技术/Bug讲解/单机修改,有兴趣的同学自行下载看吧 由于是早期录制的,有口误多包涵... 链接: http://pan.baidu.com/s/1i5JUKPf 密码: a1x ...

  7. Python递归调用

    递归调用:在调用一个函数过程中,直接或间接又调用该函数本身,称之为递归调用 递归必备的2个阶段  1递推 2回溯 当递推结束后就可以进行回溯了 Python默认设置递归层数为1000 递归示例: de ...

  8. 实验三:xen环境下的第一个虚拟机的安装

    实验名称: xen环境下的第一个虚拟机的安装 实验环境: 我们这里继续上面实验二来完成这个实验: 环境则是xen的安装环境,如下图: 开启虚拟机的的硬件辅助虚拟化功能: 实验要求: 这里我们通过安装b ...

  9. JavaWeb——tomcat manager 403 Access Denied .You are not authorized to view this page.

    403 Access Denied You are not authorized to view this page. If you have already configured the Manag ...

  10. mysql中间件kingshard

    这样写是OK的: select * from bind_history limit 10;select id, passport_id, person_id, create_time, cast(is ...