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 ...
随机推荐
- 六十六、SAP中代码格式化功能(SHIFT+F1)
一.在Delphi或PHP中,都有代码格式化工具,SAP中也有,如图 二,点击之后,没有任何反应,提示功能没有开启 三.在实用程序->设置中,选择好相关内容 四.勾选自己的相关设置 五.再点击代 ...
- SQL分组后获取其中一个字段最大值的整条记录
SELECT * FROM( SELECT id,name,counts,createDate,row_number() OVER(partition BY name ORDER BY createD ...
- 控制数据的小数位数 java / js
//java一般控制格式都是通过 DecimalFormat 来控制的.下边是个例子. import java.text.DecimalFormat; public class ControlBit ...
- ntpdate更新系统时间时报错Can't find host ntp1.aliyun.com: Servname not supported for ai_socktype (-8)
ntpdate更新系统时间时报错Can't find host ntp1.aliyun.com: Servname not supported for ai_socktype (-8) 所报错误: [ ...
- springmvc无法访问JS,CSS等文件
配置好web.xml中的dispatchservlet后,js,css,都不能正常显示 web.xml配置文件 <!-- 核心控制器 --> <servlet> <ser ...
- java 学生信息管理
题目: 一.测试要求: 1.按照测试内容要求完成程序的设计与编程: 2.将最终结果的源文件(.java)文件上传到以班级为单位,保存源程序. 3.建立学号姓名文件夹,如: ...
- 了解java常用框架
今天我看了一点看起来比较片面的东西,java常用基本床架,并且在网上搜了相关的知识和概括总结,用来继续后期的学习: 1.struts2框架,这是最经典的框架(可以说没有“之一”).可以帮你快速搭建出一 ...
- Kmeans应用
1.思路 应用Kmeans聚类时,需要首先确定k值,如果k是未知的,需要先确定簇的数量.其方法可以使用拐点法.轮廓系数法(k>=2).间隔统计量法.若k是已知的,可以直接调用sklearn子模块 ...
- MySQL新增数据,存在就更新,不存在就添加
1.插入一条数据,存在就更新,不存在就更新(必须现有唯一键)使用insert ignore语句: insert ignore into table(col1,col2) values ('a','b' ...
- 语句:{% url menu.url_name %}的作用
语句: {% url menu.url_name %} 表示跳转,上面的menu.url_name意思是menu表的url_name字段 如果menu表的url_name字段的值是sales_dash ...