【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 ...
随机推荐
- Dijkstra(迪杰斯特拉)模板
直接将模板封装在结构体里面. struct Edge{ int from,to,dist; Edge(int u, int v,int d): from(u),to(v),dist(d){} }; s ...
- linux的基本操作2
/dev/ha[a-d] IDE硬盘(过时了)/dev/sd[a-p] U盘,scsi,sata,ssd硬盘(流行)/dev/cdrom 光盘 CD-ROM/dev/mouse 鼠标 fdisk ...
- 洋葱第4场C和D题解……
只是记录一下: 我们机房讨论的结果……(当然有一个au爷一开始就秒掉了……首先先n^2或随机枚举出一对点根据抽屉原理可得枚举(n/2)^2+1次后至少有一对点全是对的然后对于两个对的点,首先考虑缩放比 ...
- 1.1.15 word调整文字与下划线之间的间距
先请按CTRL+U快捷键,或点击“下划线”按钮,然后输入一个空格,再输入文字“下划线间距”,在文字的尾部再添加一个空格.选中文字内容(注意不要选中首尾的空格),单击菜单“格式”→“字体”,在“字体”设 ...
- FluentData -Micro ORM with a fluent API that makes it simple to query a database 【MYSQL】
官方地址:http://fluentdata.codeplex.com/documentation MYSQL: MySQL through the MySQL Connector .NET driv ...
- Ubuntu 16.04 安装Mysql数据库
系统环境 Ubuntu 16.04; 安装步骤 1.通过以下环境安装mysql服务端与客户端软件 sudo apt-get install mysql-server apt-get isntall m ...
- 在KVM里装个pfSense
第一步:安装配置 virsh destroy router-wan1- virsh undefine router-wan1- qemu-img create -f qcow2 -o size=8G ...
- 【比赛打分展示双屏管理系统-专业版】Other.ini 配置文件解读以及排行榜界面及专家评语提交展示等具体配置
第一个问题:Other.ini配置文件的解读: 在软件根目录下,找到Other.ini配置文件,打开如下: 配置文件解读: iOrderIDOrXSID:默认为0,按照软件 选项/排行榜和奖项 的设置 ...
- C# 数字转换成大写
/// <summary> /// 数字转大写 /// </summary> /// <param name="Num">数字</para ...
- AtomicInteger类和int原生类型自增鲜明的对比
AtomicInteger这个类的存在是为了满足在高并发的情况下,原生的整形数值自增线程不安全的问题.比如说 int i = 0 ; i++; 上面的写法是线程不安全的. 有的人可能会说了,可以使 ...