poj2778 矩阵乘法+ac自动机
题: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自动机的更多相关文章
- 【BZOJ4861】[Beijing2017]魔法咒语 矩阵乘法+AC自动机+DP
[BZOJ4861][Beijing2017]魔法咒语 题意:别看BZ的题面了,去看LOJ的题面吧~ 题解:显然,数据范围明显的分成了两部分:一个是L很小,每个基本词汇长度未知:一个是L很大,每个基本 ...
- POJ2778 DNA Sequence(AC自动机 矩阵)
先使用AC自动机求得状态转移关系,再建立矩阵,mat[i][j]表示一步可从i到j且i,j节点均非终止字符的方案数,则此矩阵的n次方表示n步从i,到j的方法数. #include<cstdio& ...
- [poj2778]DNA Sequence(AC自动机+矩阵快速幂)
题意:有m种DNA序列是有疾病的,问有多少种长度为n的DNA序列不包含任何一种有疾病的DNA序列.(仅含A,T,C,G四个字符) 解题关键:AC自动机,实际上就是一个状态转移图,注意能少取模就少取模, ...
- [poj2778 DNA Sequence]AC自动机,矩阵快速幂
题意:给一些字符串的集合S和整数n,求满足 长度为n 只含charset = {'A'.'T‘.'G'.'C'}包含的字符 不包含S中任一字符串 的字符串的种类数. 思路:首先对S建立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 ...
- BZOJ 1898: [Zjoi2004]Swamp 沼泽鳄鱼(矩阵乘法)
可以发现,如果没有鳄鱼,那么就是裸地一道题,但是可以发现鳄鱼最多每12次重复,那么就少于12的那部分dp,其他的就矩阵乘法就行了 PS:第一次吧矩阵乘法AC了好开心QAQ CODE: #include ...
- 【POJ2778】AC自动机+矩阵乘法
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14758 Accepted: 5716 Descrip ...
- 【poj2778-DNA Sequence】AC自动机+矩阵乘法
题意: (只含AGCT)给定m个病毒串,让你构造一个长度为n的字符串(也只含有AGCT),问有多少种方案.n很大:1<=n<=2000000000 题解: 用病毒串建立AC自动机(num个 ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
随机推荐
- 【转】美团 MySQL 数据实时同步到 Hive 的架构与实践
文章转载自公众号 美团技术团队 , 作者 萌萌 背景 在数据仓库建模中,未经任何加工处理的原始业务层数据,我们称之为ODS(Operational Data Store)数据.在互联网企业中,常见的 ...
- Spring 控制反转容器(Inversion of Control – IOC)
系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Contro ...
- 装饰者模式(Decorator Pattern)C#版本的
仍然来自 zhili https://www.cnblogs.com/zhili/p/DecoratorPattern.html 谢谢啊 呵呵 ---------------------------- ...
- HDU - 2602 Bone Collector(01背包讲解)
题意:01背包:有N件物品和一个容量为V的背包.每种物品均只有一件.第i件物品的费用是volume[i],价值是value[i],求解将哪些物品装入背包可使价值总和最大. 分析: 1.构造二维数组: ...
- 外部 Storage Provider【转】
如果 Kubernetes 部署在诸如 AWS.GCE.Azure 等公有云上,可以直接使用云硬盘作为 Volume,下面是 AWS Elastic Block Store 的例子: 要在 Pod 中 ...
- c++ opencv 动态内存
1.CvMemStorage定义动态内存存储器 内存存储器是一个用来存储诸如序列.轮廓.图形和子划分等动态增长数据结构的底层结构 2.示例 CvMemStorage *mems = cvCreat ...
- 利用方法HttpUtility.HtmlEncode来预处理用户输入
利用方法HttpUtility.HtmlEncode来预处理用户输入.这样能阻止用户用链接注入JavaScript代码或HTML标记,比如//Store/Broswe?Genre=<script ...
- 简单的说一下react路由(逆战班)
现代前端大多数都是SPA(单页面程序),也就是只有一个HTML页面的应用程序,因为它的用户体验更好,对服务器压力更小,所以更受欢迎,为了有效的使用单个页面来管理原来多页面的功能,前端路由应运而生. 前 ...
- jdk8安装
==安装jdk1.8== [root@ycj ~]# mkdir -p /usr/local/src/jdk //创建目录 [root@ycj jdk]# cd /usr/local/src/jdk ...
- python单链表的基本操作思路
单链表: 1.定义链表 class ListNode: # 定义节点 def __init__(self, x): self.val = x # 节点当前值 self.next = None # 指向 ...