POJ 2778 AC自动机+矩阵幂 不错的题

2024-05-28 04:58
文章标签 矩阵 poj 不错 ac 自动机 2778

本文主要是介绍POJ 2778 AC自动机+矩阵幂 不错的题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

有空再重新做下,对状态图的理解很重要

题解:
http://blog.csdn.net/morgan_xww/article/details/7834801


另外做了矩阵幂的模板:

//ac.sz是矩阵的大小
void mulmtr(long long x[MAXNODE][MAXNODE],long long y[MAXNODE][MAXNODE])//y=x*y
{ll tmp[MAXNODE][MAXNODE];for(int i=0;i<ac.sz;i++){for(int j=0;j<ac.sz;j++){tmp[i][j]=0;for(int k=0;k<ac.sz;k++)tmp[i][j] +=x[i][k]*y[k][j];tmp[i][j] %=MOD;}}for(int i=0;i<ac.sz;i++)for(int j=0;j<ac.sz;j++)y[i][j]=tmp[i][j];
}
void Mtrmi(ll mtr[MAXNODE][MAXNODE],int n)
{for(int i=0;i<ac.sz;i++){for(int j=0;j<ac.sz;j++){if(i == j)ans[i][j]=1;//E矩阵else ans[i][j]=0;}}while(n){if(n&1){mulmtr(mtr,ans);}mulmtr(mtr,mtr);n/=2;}
}




代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <iostream>
using namespace std;#define ll long longconst int MAXNODE  = 15*15;
const int SSIZE  = 2000000000+100;
const int MOD = 100000;
const int SIGMA_SIZE = 4;
const int SIZE = 20;ll mtr[MAXNODE][MAXNODE];
ll ans[MAXNODE][MAXNODE];
int danger[MAXNODE];struct AC
{int f[MAXNODE];int val[MAXNODE];int last[MAXNODE];int cnt[MAXNODE];int ch[MAXNODE][SIGMA_SIZE];int sz;void init(){memset(ch[0],0,sizeof(ch[0]));memset(cnt,0,sizeof(cnt));f[0]=0;///sz=1;}inline int idx(char x){if(x == 'A')return 0;if(x == 'T')return 1;if(x == 'C')return 2;if(x == 'G')return 3;}void insert(char *s, int v){int n=strlen(s),u=0;for(int i=0;i<n;i++){int id= idx(s[i]);if(!ch[u][id]){memset(ch[sz],0,sizeof(ch[sz]));val[sz]=0;ch[u][id]=sz++;}u=ch[u][id];}val[u]=v;danger[u]=1;}void getfail(){queue<int>q;f[0]=0;for(int c=0;c<SIGMA_SIZE;c++){int u=ch[0][c];if(u){q.push(u);f[u]=0;last[u]=0;}}while(!q.empty()){int r=q.front();q.pop();for(int c=0;c<SIGMA_SIZE;c++){int u=ch[r][c];//if(!u)continue;if(!u){ch[r][c]=ch[f[r]][c];//continue;}q.push(u);int v=f[r];while(v &&!ch[v][c])v=f[v];f[u]=ch[v][c];//last[u]=val[f[u]]?f[u]:last[f[u]];danger[u] |= danger[f[u]];}}}
};
void init()
{memset(mtr,0,sizeof(mtr));memset(danger,0,sizeof(danger));
}AC ac;char str[SIZE];void mulmtr(long long x[MAXNODE][MAXNODE],long long y[MAXNODE][MAXNODE])//y=x*y
{ll tmp[MAXNODE][MAXNODE];for(int i=0;i<ac.sz;i++){for(int j=0;j<ac.sz;j++){tmp[i][j]=0;for(int k=0;k<ac.sz;k++)tmp[i][j] +=x[i][k]*y[k][j];tmp[i][j] %=MOD;}}for(int i=0;i<ac.sz;i++)for(int j=0;j<ac.sz;j++)y[i][j]=tmp[i][j];
}
void Mtrmi(ll mtr[MAXNODE][MAXNODE],int n)
{for(int i=0;i<ac.sz;i++){for(int j=0;j<ac.sz;j++){if(i == j)ans[i][j]=1;//E矩阵else ans[i][j]=0;}}while(n){if(n&1){mulmtr(mtr,ans);}mulmtr(mtr,mtr);n/=2;}
}int main()
{//freopen("poj2788.txt","r",stdin);int n,m;while(~scanf("%d%d",&m,&n)){init();ac.init();for(int i=1;i<=m;i++){scanf("%s",str);ac.insert(str,i);}ac.getfail();for(int i=0;i<ac.sz;i++)if(!danger[i])for(int j=0;j<4;j++)if(!danger[ac.ch[i][j]]){mtr[i][ac.ch[i][j]]++;}Mtrmi(mtr,n);//* for(int i=0;i<ac.sz;i++){for(int j=0;j<ac.sz;j++)printf("%lld|%lld ",mtr[i][j],ans[i][j]);putchar('\n');}*////for(int i=1;i<ac.sz;i++)ans[0][0]+=ans[0][i]%MOD;printf("%I64d\n",ans[0][0]%MOD);}return 0;
}


这篇关于POJ 2778 AC自动机+矩阵幂 不错的题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1009599

相关文章

Android开发的一些不错的学习资料

一个有趣的学习网站:http://hukai.me/android-training-course-in-chinese/index.html 这个是一些基础的教程,看看很好的,赏心悦目。 工具下载网站:http://www.androiddevtools.cn/ 这里的东西很不错,AndroidStudio,UIStyle的压缩工具,开发必备。

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符。然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<string

poj 3294(Life Forms) 2分+ 后缀数组

我曾用字符串hash写,但是超时了。只能用后最数组了。大致思路:用不同的符号吧字符串连接起来,构建后缀数组,然后2分答案,依次扫描后缀数组,看是否瞒住条件。 VIEW CODE #include<cstdio>#include<vector>#include<cmath>#include<algorithm>#include<cstring>#include<cassert>#

poj 2391 Ombrophobic Bovines (网络流)

这是一道很经典的网络流的题目。首先我们考虑假如我们的时间为无穷大。我们吧每个点拆成2个点 i和i' .。虚拟源点s和汇点t。对于每个点建边(s,i, a[i])  (i‘,t,ib[i]) 。 其中a[i]为给点有多少牛,b[i]为容量。i和j连通 建边 (i,j',inf);如果最大流==所有牛的个数,就可能装下所有的牛。那么现在我们考虑时间。假设最大时间为T.那么如果i到j的的最短时间>T

poj 1330 LCA 最近公共祖先

水题目。直接上代码了。 VIEW CODE #include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<string>#include<cstring>#include<map>#include<vector>#

poj 3160 Father Christmas flymouse 强连通+dp

首先我们可以确定的是,对于val值小于0的节点都变成0.   假设一个集合内2个房间都能任意到达,那么我就可以吧集合内的所有点的价值都取到,并且可以达到任一点。实际上集合内的每个点是相同的,这样的集合就是一个强连通分量。 那么我们就可以用tarjin算法进行强连通缩点, 最后形成一个dag的图。在dag的图上面进行dp。可以先用拓扑排序后dp。或者建反响边记忆化搜索 。 VIEW

RTSP协议,这个写的不错,赚了

1. RTSP连接的建立过程       RTSPServer类用于构建一个RTSP服务器,该类同时在其内部定义了一个RTSPClientSession类,用于处理单独的客户会话。       首先创建RTSP服务器(具体实现类是DynamicRTSPServer),在创建过程中,先建立Socket(ourSocket)在TCP的554端口进行监听,然后把连接处理函数句柄(RTSPSer

推荐算法之矩阵分解实例

矩阵分解的数据利用的上篇文章的数据,协同过滤 用到的知识 python的surprise k折交叉验证 SVD SVDpp NMF 算法与结果可视化 # 可以使用上面提到的各种推荐系统算法from surprise import SVD,SVDpp,NMFfrom surprise import Datasetfrom surprise import print_perf

江协科技51单片机学习- p16 矩阵键盘

🚀write in front🚀   🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​  💬本系列哔哩哔哩江科大51单片机的视频为主以及自己的总结梳理📚  前言: 本文是根据哔哩哔哩网站上“江协科技51单片机”视频的学习笔记,在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习

使用matlab的大坑,复数向量转置!!!!!变量区“转置变量“功能(共轭转置)、矩阵转置(默认也是共轭转置)、点转置

近期用verilog去做FFT相关的项目,需要用到matlab进行仿真然后和verilog出来的结果来做对比,然后计算误差。近期使用matlab犯了一个错误,极大的拖慢了项目进展,给我人都整emo了,因为怎么做仿真结果都不对,还好整体的代码都是我来写的,慢慢往下找就找到了问题的来源,全网没有看到多少人把这个愚蠢的错误写出来,我来引入一下。 代码错误的表现:复数向量的虚部被取反,正数变成负数,负数