题意

题目给出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. 文献--A Survey on Server-side Approaches to Securing Web Applications

    Q:1.如何定义XSS攻击? 2.taint-based 啥意思? 3. second-order vulnerabilities 啥意思?

  2. C++学习(三十八)(C语言部分)之 排序(冒泡 选择 插入 快排)

    算法是解决一类问题的方法排序算法 根据元素大小关系排序 从小到大 从大到小冒泡 选择 插入 快排希尔排序 归并排序 堆排序 冒泡排序 从头到尾比较 每一轮将最大的数沉底 或者最小数字上浮 选择排序 1 ...

  3. 基于tensorflow的逻辑分类

    #!/usr/local/bin/python3 ##ljj [2] ##logic classify model import tensorflow as tf import matplotlib. ...

  4. 关于C++指针

    C++继承于C,对C的语法做了一些扩展.C语言中的指针占一个机器长度(32位处理器上一个指针占32位,64位处理器上安装64位操作系统一个指针占64位),指针的作用就是使用这块内存(4字节或者8字节) ...

  5. MySQL--Profiling和Trace使用

    使用MySQL Profiling ##=====================================## ## 查看PROFILING是否开启 SELECT @@profiling ## ...

  6. jQuery基础(三)事件

    1.鼠标事件 jQuery鼠标事件之click与dblclick事件 click方法用于监听用户单击操作,dbclick方法用于监听用户双击操作. 方法一:$ele.click() 绑定$ele元素, ...

  7. find查找文件的时间问题

    很多细节方面的东西没有到真正用的时候,是觉察不出来的,因为这个时间的问题出了问题,现在好好理一下,这个find的时间很容易就搞混了,一段时间不用,也忘了,也反映出来了自己的基础知识不是很牢固啊   f ...

  8. openstry lua redis实现负载均衡

    需求: 通过URI地址http://10.0.0.148/test2?uuid=123的uuid参数值的第一位,去实现redis的负载均衡 若uuid第一位为1,那么去10.0.0.148的redis ...

  9. windows 安装lua-5.3.4 --引用自https://blog.csdn.net/wangtong01/article/details/78296369

    版权声明:本文为博主原创文章,转载时请标明出处.http://blog.csdn.net/wangtong01 https://blog.csdn.net/wangtong01/article/det ...

  10. Python历史与安装

    1.Python发展历史 起源 Python的作者,Guido von Rossum,荷兰人.1982年,Guido从阿姆斯特丹大学获得了数学和计算机硕士学位.然而,尽管他算得上是一位数学家,但他更加 ...