【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 的基因中有多少是不包含这些有害片段的. 分析:也是断断续续做了一 ...
随机推荐
- SQLite之写一个表
1.首先你需要一个路径. 获取document目录并返回数据库目录 - (NSString *)dataFilePath{ NSArray *paths = NSSearchPathForDirect ...
- mac下163企业邮箱客户端的配置
一 添加账户 添加账户->添加其他邮件账户->输入电子邮件地址和密码.(全名随意起). 二 收件服务器和发件服务器的设置 收件服务器:pop.qiye.163. ...
- perl DBI 学习总结(转载)
perl DBI 学习总结 源文地址:http://blog.csdn.net/like_zhz/article/details/5441946 DBI和DBD的不同关系模型: ########### ...
- 位bit——字节Byte???
1.换算 每8个位(bit)组成一个字节(byte) 位bit简写为小写字母“b”,字节Byte简写为大写字母“B” 8*b=1*B 1024*B=1*KB 1024*K=1MB 2.举例 一个英文字 ...
- Matlab实现单(双)极性(不)归零码
Matlab实现单(双)极性(不)归零码 内容大纲 Matlab实现单极性不归零波形(NRZ),0 1 幅值 Matlab实现单极性归零波形(RZ),0 1 幅值 Matlab实现双极性不归零波形,- ...
- shell操作文件的几条命令:删除最后一列、删除第一行、diff等
删除文件第一行: sed '1d' filename 删除文件最后一列: awk '{print $NF}' filename awk删除重复行的命令:awk '{if (!seen[$0]++) { ...
- 调用webservice客户端方法 runtime modeler error: Wrapper class ××× is not found. Have you run APT to generate them?
用wsimport生成webservice的客户端以后,调用客户端生成方法时总是出现 runtime modeler error: Wrapper class stardand.nrcms.nckin ...
- DES,3DES,AES这三种对称密钥的区别与联系
DES:Data Encryption Standard(数据加密标准,又美国国密局,选中的IBM的方案,密钥长度为56,标准提出是要使用64位长的密钥,但是实际中DES算法只用了64位中的56位密钥 ...
- Why does uitableview cell remain highlighted?
What would cause a tableview cell to remain highlighted after being touched? I click the cell and ca ...
- php 设计API之优化 记
服务器端 可以考虑使用rest实现,清晰url:put http://aa.com/news 客户端 curl实现muliti机制,实现多线程并发,节省多接口调用的时间 curl实现keepalive ...