poj 2778 AC自动机 + 矩阵快速幂

2024-04-09 15:58
文章标签 快速 矩阵 poj ac 自动机 2778

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

//	poj 2778 AC自动机 + 矩阵快速幂
//
//	题目链接:
//		
//		http://poj.org/problem?id=2778
//
//	解题思路:
//
//		建立AC自动机,确定状态之间的关系,构造出,走一步
//	能到达的状态矩阵,然后进行n次乘法,就可以得到状态间
//	走n步的方法数.
//	精髓:
//		1):这个ac自动机有一些特别,根节点是为空串,然而
//	每走一步的时候,如果没法走了,这时候,不一定是回到根
//	节点,因为有可能单个的字符时病毒,这样,不是随便就能达到
//	所谓的根节点的,所以每次初始化的时候,不能是0,而应该是
//	-1.
//
//	感悟:
//
//		这道AC自动机,开始我是完全不会,知道是AC自动机+矩阵快速幂
//	开始,自以为AC自动机构造的很对,而且样例都过了好嘛,结果一直是
//	wrong answer.我就不信邪了,肯定是博主博客有错误,我就将博主的
//	交了一发,然而,博主的过了,我的没过.哎,一阵伤心,但心里也是再次
//	燃起了希望之火,还是可以搞得.然而我就仔细研究,对拍呗,自己造了
//	几个样例.发现下面这组:
//		4 2
//		A
//		C
//		T
//		GT
//	这组样例,答案应该是1,而我的答案是3.我仿佛一下子恍然大悟,发现
//	单个字符是病毒,不能走回根节点.明白了过后,一改,就AC了,虽然速度
//	有点慢,但是我发现自己对AC自动机的理解又有了一点小小的新的拓展
//	虽然作为菜鸟的我敢于怀疑是一件好事,但是自己的不对就是不对,不要
//	因为自己的自信就去刻意寻找别人的错误,认为别人是错误的.有着一颗
//	敢于承认错误,并且接受正确观念,并明悟的人,我觉得光明,就在前方!#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;typedef long long ll;const int MAX_NODE = 110;
const ll MOD = 100000;
const int MAX_N = 110;struct Matrix{ll mat[MAX_N][MAX_N];
}res;int n,m;struct Aho_Corasick{int ch[MAX_NODE][4];bool val[MAX_NODE];int f[MAX_NODE];//int last[MAX_NODE];int sz;void init(){memset(ch[0],-1,sizeof(ch[0]));val[0] = 0;sz = 1;f[0] = 0;//last[0] = 0;}int idx(char c){if (c == 'A')return 0;if (c == 'T')return 1;if (c == 'C')return 2;return 3;}void insert(char *s){int u = 0;int n = strlen(s);for (int i=0;i<n;i++){int c = idx(s[i]);if (ch[u][c]==-1){memset(ch[sz],-1,sizeof(ch[sz]));val[sz] = 0;ch[u][c] = sz++;}u = ch[u][c];}val[u] = true;}void getfail(){queue<int> que;f[0] = 0;for (int c = 0;c < 4;c++){int u = ch[0][c];if (u!=-1){que.push(u);f[u] = 0;//	last[u] = 0;}else{ch[0][c] = 0; //表示当此c单个字符不是病毒的时候,则可以走回根}}while(!que.empty()){int r = que.front();que.pop();if (val[f[r]]) // 当r的某个后缀为病毒的时候标记此rval[r] = true;for (int c = 0; c < 4;c++){int u = ch[r][c];if (u == -1){ch[r][c] = ch[f[r]][c]; //把不存在的边接上去continue;}que.push(u);int v = f[r];while(v && ch[v][c]==-1)v = f[v];f[u] = ch[v][c];//last[u] = val[f[u]] ? f[u] : last[f[u]];}}}void get_matrix(){memset(res.mat,0,sizeof(res.mat));for (int u=0;u<sz;u++){for (int c = 0;c < 4;c++){if (!val[u] && !val[ch[u][c]])res.mat[u][ch[u][c]]++;}}}}ac;Matrix Mulity(Matrix a,Matrix b){Matrix ans;for (int i=0;i < ac.sz;i++)for (int j=0;j < ac.sz;j++){ans.mat[i][j] = 0;for (int k=0;k < ac.sz ;k++)ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j])%MOD;ans.mat[i][j] %= MOD;}return ans;
}Matrix Matrix_power(Matrix a,int b){Matrix ans;memset(ans.mat,0,sizeof(ans.mat));for (int i=0;i<ac.sz;i++)ans.mat[i][i] = 1;while(b){if (b & 1)	ans = Mulity(ans,a);a = Mulity(a,a);b >>=1;}return ans;
}void print(Matrix r){for (int i=0;i<ac.sz;i++){for (int j=0;j<ac.sz;j++)cout << r.mat[i][j] << " ";cout << endl;}
}void input(){ac.init();char s[20];for (int i=1;i<=m;i++){scanf("%s",s);ac.insert(s);}ac.getfail();ac.get_matrix();
//	print(res);res = Matrix_power(res,n);
//	cout << endl;
//	print(res);ll ans = 0;for (int i=0;i<ac.sz;i++){ans = (ans + res.mat[0][i])%MOD;}cout << ans%MOD << endl;
}int main(){//freopen("1.txt","r",stdin);while(scanf("%d%d",&m,&n)!=EOF){//	puts("-------");input();}return 0;
}

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



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

相关文章

Linux如何快速检查服务器的硬件配置和性能指标

《Linux如何快速检查服务器的硬件配置和性能指标》在运维和开发工作中,我们经常需要快速检查Linux服务器的硬件配置和性能指标,本文将以CentOS为例,介绍如何通过命令行快速获取这些关键信息,... 目录引言一、查询CPU核心数编程(几C?)1. 使用 nproc(最简单)2. 使用 lscpu(详细信

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

C/C++中OpenCV 矩阵运算的实现

《C/C++中OpenCV矩阵运算的实现》本文主要介绍了C/C++中OpenCV矩阵运算的实现,包括基本算术运算(标量与矩阵)、矩阵乘法、转置、逆矩阵、行列式、迹、范数等操作,感兴趣的可以了解一下... 目录矩阵的创建与初始化创建矩阵访问矩阵元素基本的算术运算 ➕➖✖️➗矩阵与标量运算矩阵与矩阵运算 (逐元

MybatisX快速生成增删改查的方法示例

《MybatisX快速生成增删改查的方法示例》MybatisX是基于IDEA的MyBatis/MyBatis-Plus开发插件,本文主要介绍了MybatisX快速生成增删改查的方法示例,文中通过示例代... 目录1 安装2 基本功能2.1 XML跳转2.2 代码生成2.2.1 生成.xml中的sql语句头2

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

一文教你Java如何快速构建项目骨架

《一文教你Java如何快速构建项目骨架》在Java项目开发过程中,构建项目骨架是一项繁琐但又基础重要的工作,Java领域有许多代码生成工具可以帮助我们快速完成这一任务,下面就跟随小编一起来了解下... 目录一、代码生成工具概述常用 Java 代码生成工具简介代码生成工具的优势二、使用 MyBATis Gen

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

SpringBoot快速搭建TCP服务端和客户端全过程

《SpringBoot快速搭建TCP服务端和客户端全过程》:本文主要介绍SpringBoot快速搭建TCP服务端和客户端全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录TCPServerTCPClient总结由于工作需要,研究了SpringBoot搭建TCP通信的过程

一文教你Python如何快速精准抓取网页数据

《一文教你Python如何快速精准抓取网页数据》这篇文章主要为大家详细介绍了如何利用Python实现快速精准抓取网页数据,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录1. 准备工作2. 基础爬虫实现3. 高级功能扩展3.1 抓取文章详情3.2 保存数据到文件4. 完整示例

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完