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 ...
随机推荐
- PHP网页简单的计算机源代码
还是那样老师留的作业,百度一波和老师留的作业有区别!自己写一下!! 作业题目: 实现PHP网页的计算器功能.至少实现运算符 +.-.*./.取模的功能. (提示:可以点击‘等号’进行运算,也可以另外添 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-map-marker
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- 51nod 1105:第K大的数
1105 第K大的数 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * ...
- 基于UWB技术的DW1000芯片简单解析
近些年来随着物联网和机器人技术的大发展,精确定位技术的热度也随之攀升.目前精确定位的技术有很多,如基于wifi.RFID.zigbee.超声波.UWB等技术都可以实现精准定位.由于技术的不同,精度也不 ...
- Day1-T1
原题目 Describe:普通前缀和(当然有升级版的题目,范围3000+) code: #include<bits/stdc++.h> #define maxn 1010 #define ...
- 【转】modelBuilder.Configurations.AddFromAssembly in EF Core
EntityFramework 6.x protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnMode ...
- HZNU-ACM寒假集训Day2小结 二分答案
Day2 ---二分 这里直接给出模板 两种对应不同的情况 可以借助数轴理解 int bsearch_1(int l, int r) { while (l < r) { ; if (check( ...
- C#高级编程(第9版) 第08章 委托、lambda表达式和事件 笔记
本章代码分为以下几个主要的示例文件: 1. 简单委托 2. 冒泡排序 3. lambda表达式 4. 事件示例 5. 弱事件 引用方法 委托是寻址方法的.NET版本.在C++中函数 ...
- VS Code 配置vue开发环境
一.插件 网上搜索vscode插件的文章,动辄十几个,其实根本用不了那么多,很多插件的作用还有重叠,电脑性能还被白白浪费.这里精简为主,每一个插件都发挥它最大的作用,并尽量说明它们的作用 Vetur ...
- id就是方法名,如何调用;批量input怎么获取他们的key值作为参数
1.很多Dom的时候,一个个写会比较麻烦,我用ID记载他的方法名: 2.很多input,在数据交互的时候一个个获取会比较繁琐,给一个方法,批量获取. <div id="searchSt ...