题:http://poj.org/problem?id=2778

题意:给定m个模式串,问长度为n的字符串不包含这些模式串的有几种可能

分析:因为n很大,所以考虑矩阵ksm来解决,构造一个矩阵res[i][j]表示从i到j有多少种方案数,我们先考虑只走1步后的res数组的构造,i节点能走到j节点当且仅当i节点和j节点都是安全的点,这个安全的点就是用m个模式串构成的trie树上的end[],显然根结点是安全结点。 一个非根结点是危险结点的充要条件是: 它的路径字符串本身就是一个不良单词 ,或 它的路径字符串的后缀对应的结点(即fail[i])是危险结点。预处理完ac自动机后,就可以处理res数组,这个res数组就相当于在学离散数学时的矩阵;剩下的n步就交给ksm这个res数组即可,答案就是sum(res[0][i])

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const int mod=1e5;
const int maxn=;///只有4个字母
const int N=1e3+;
struct ac{
int trie[N][maxn],fail[N];
int tot,root;
bool end[N];
ll res[N][N],ans[N][N],tmp[N][N];
int newnode(){
for(int i=;i<maxn;i++){
trie[tot][i]=-;
}
end[tot++]=;
return tot-;
}
void init(){
tot=;
root=newnode();
memset(res,,sizeof(res));
memset(ans,,sizeof(ans));
memset(end,false,sizeof(end));
}
int getid(char c){
if(c=='A')
return ;
if(c=='C')
return ;
if(c=='T')
return ;
if(c=='G')
return ;
}
void insert(char *buf,int id){
int now=root,len=strlen(buf);
for(int i=;i<len;i++){
int x=getid(buf[i]);
if(trie[now][x]==-)
trie[now][x]=newnode();
now=trie[now][x];
}
end[now]=true;//它的路径字符串本身就是一个不良单词
}
void getfail(){ queue<int>que;
while(!que.empty())
que.pop();
fail[root]=root;
for(int i=;i<maxn;i++)
if(trie[root][i]==-)
trie[root][i]=root;
else{
fail[trie[root][i]]=root;
que.push(trie[root][i]);
}
while(!que.empty()){
int now=que.front();
que.pop();
if(end[fail[now]])//它的路径字符串的后缀对应的结点(即fail[i])是危险结点
end[now]=true;
for(int i=;i<maxn;i++){
if(trie[now][i]!=-){
fail[trie[now][i]]=trie[fail[now]][i];
que.push(trie[now][i]);
}
else
trie[now][i]=trie[fail[now]][i];
}
}
} void path(){
for(int i=;i<tot;i++){
for(int j=;j<maxn;j++)
if(!end[i]&&!end[trie[i][j]]){
// cout<<i<<"!!"<<j<<endl;
res[i][trie[i][j]]++;
} }
}
void mul(ll a[][N],ll b[][N]){
for(int i=;i<tot;i++)
for(int j=;j<tot;j++){
tmp[i][j]=;
for(int k=;k<tot;k++)
tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
}
for(int i=;i<tot;i++)
for(int j=;j<tot;j++)
a[i][j]=tmp[i][j];
}
ll solve(int n){ for(int i=;i<tot;i++)
ans[i][i]=;
while(n){
if(n&){
mul(ans,res);
}
n>>=;
mul(res,res);
}
ll ANS=;
for(int i=;i<tot;i++)
ANS=(ANS+ans[][i])%mod;
return ANS;
}
}AC;
char s[];
int main(){
int m,n;
scanf("%d%d",&m,&n);
AC.init();
for(int i=;i<=m;i++){
scanf("%s",s);
AC.insert(s,i);
}
AC.getfail();
AC.path();
printf("%lld\n",AC.solve(n));
return ;
}

poj2778 矩阵乘法+ac自动机的更多相关文章

  1. 【BZOJ4861】[Beijing2017]魔法咒语 矩阵乘法+AC自动机+DP

    [BZOJ4861][Beijing2017]魔法咒语 题意:别看BZ的题面了,去看LOJ的题面吧~ 题解:显然,数据范围明显的分成了两部分:一个是L很小,每个基本词汇长度未知:一个是L很大,每个基本 ...

  2. POJ2778 DNA Sequence(AC自动机 矩阵)

    先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数. #include<cstdio& ...

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

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

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

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

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

  6. BZOJ 1898: [Zjoi2004]Swamp 沼泽鳄鱼(矩阵乘法)

    可以发现,如果没有鳄鱼,那么就是裸地一道题,但是可以发现鳄鱼最多每12次重复,那么就少于12的那部分dp,其他的就矩阵乘法就行了 PS:第一次吧矩阵乘法AC了好开心QAQ CODE: #include ...

  7. 【POJ2778】AC自动机+矩阵乘法

    DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...

  8. 【poj2778-DNA Sequence】AC自动机+矩阵乘法

    题意: (只含AGCT)给定m个病毒串,让你构造一个长度为n的字符串(也只含有AGCT),问有多少种方案.n很大:1<=n<=2000000000 题解: 用病毒串建立AC自动机(num个 ...

  9. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

随机推荐

  1. 十七、SAP中使用SQL语句读取一条数据

    一.需要说明的是SAP不同类型的结构体类型之间是不能随意赋值的,如果需要赋值,可以使用CORRESPONDING FIELDS OF关键字, 不同类型结构体中同名的成员会被赋值,代码如下: 二.输出代 ...

  2. zerone 01串博弈问题

    近日领到了老师的期末作业 其中有这道 01 串博弈问题: 刚开始读题我也是云里雾里 但是精读数遍 “细品” 之后,我发现这是一个 “动态规划” 问题.好嘞,硬着头皮上吧. 分析问题:可知对每个人有两手 ...

  3. 干货分享:学术Essay写作流程及写作技巧详解

    Academic essay是指留学生作业中的一种,其范围非常广泛,可以是任何一种话题.而学术essay主要是指其中比较正式的.客观的话题,有明确的研究目的与研究对象.例如“Research on t ...

  4. torch.cuda.FloatTensor

    Pytorch中的tensor又包括CPU上的数据类型和GPU上的数据类型,一般GPU上的Tensor是CPU上的Tensor加cuda()函数得到. 一般系统默认是torch.FloatTensor ...

  5. python 同步异步,并发并行,同步锁

    并发:系统具有处理多个任务(动作)的能力 并行:系统具有同时处理多个任务(动作)的能力 同步:当进程执行到一个IO(等待外部数据)的时候,需要等待,等待即同步 异步:当进程执行到一个IO(等待外部数据 ...

  6. lastz

    lastz sequence1.fasta sequence2.fasta 其中,sequence1.fasta是reference genome :sequence2.fasta是需要比对的geno ...

  7. c++程序—三目运算符

    #include<iostream> using namespace std; #include<string> int main() { //三目运算符 ; ; ; c = ...

  8. Adobe Photoshop CC2014 for MAC 详细破解步骤

    1,安装Adobe Photoshop CC2014 for MAC,可以断网安装,如果不断网的话,需要申请一个Adobe ID,是免费申请. 2,下载破解工具,https://sdifen.ctfi ...

  9. (转) Windows如何区分鼠标双击和两次单击

    Windows如何区分鼠标双击和两次单击 http://lbsloveldm.blog.hexun.com/12212875_d.html 在Windows平台上,鼠标左键的按下.松开.快速的两次点击 ...

  10. arm安装cuda9.0,tensorflow-gpu, jetson tx2安装Jetpack踩坑合集

    因为要在arm(aarch64)架构的linux环境中安装tensorflow-gpu,但是官方tf网上没有对应的版本,所以我们找了好久,找到一个其他人编译好的tensorflow on arm的gi ...