『2019Summer Algorithms』
一个暑假两次集训,感觉学了好多好多的东西,也挖了好多好多的坑,于是就决定写一篇关于算法的总结,用于熟悉新算法,也留下一点对新算法的理解。
AC自动机
简单的说就是在\(trie\)树上实现\(KMP\),用于多模式串的匹配。
而\(AC\)自动机的理解就在于\(fail\)指针,\(fail\)指针是实现多模式串匹配的关键。每次匹配失败后,\(fail\)指针会指向一个当前匹配串的最长真后缀,数次跳跃后,就能实现对文本串的一段在\(trie\)树进行所有可能的匹配。
而对于\(fail\)指针的求解,用\(bfs\)实现。\(AC\)自动机的时间复杂度是线性的(一般情况下)。
好像\(AC\)自动机还有一个拓扑建图优化,还没有学。
manacher算法
\(manacher\)算法用于求解一个字符串每一个位置的最长回文字串。
这个算法其实和\(KMP\)的思想差不多,只要用已知信息去推后面的信息就可以了。具体地,可以记录当前最大的回文右端点,然后画一下对称图,就可以推了,不是很难。
博客这篇,模板题这里,可以看\(HL\ Day4\)的课件。
ExKMP算法
\(KMP\)算法的拓展,又称\(z-algorithm\),用于求解以下问题:
给你两个字符串\(s,t\),长度分别为\(n,m\),请输出\(s\)的每一个后缀与t的最长公共前缀。
思想和\(KMP\),\(manacher\)都是一样的,就是从前往后推。由于相邻两个位置的答案有很大一部分是重复匹配的,所以可以根据上一次的答案考虑,需要分两种情况讨论。
不是很好写,好像下标还只能从\(0\)开始,从\(1\)开始会非常别扭。
块状树
把分块思想放在树上,就是树分块。
用\(dfs\)遍历树,把连续遍历到的一段节点加在一个块里。然后就可以对树子树信息进行维护了。
还是和分块一样,块内设法直接维护,边角暴力。这样进行分块是可以支持修改和动态加点的,但是不是稳定算法,会被菊花图卡掉。
模板题这里。
树同构
也可以说是树哈希算法,主要用于判定树的形态。
一般来说用的是最小表示法,像树形\(dp\)一样,先获取每个子树的\(hash\)值,然后组合成一个新的序列,再\(hash\)一个值返回即可。
当树是无根树的时候,还要先找以下重心作为根,当然也要考虑双重心的情况。
模板题这里。
类欧几里得算法
好像和欧几里得算法没什么关系,是用来计算整除求和式的。
主要思想就是分类,然后分治,比欧几里得算法稍微复杂一点,就是推公式吧,套路还是拆一下求和式,下取整。
模板题这里。
整体分治
简单的说就是对于多个询问同时进行二分答案,像二分答案一样判定询问的真实答案位于哪一侧,然后对询问进行分类,就变成一个分治算法了。
真正理解点在于询问分类,这是分治算法的核心,得到的子问题是独立的。这样就可以理解为什么修改操作也能参与分类了。
代码上就是要想好用什么数据结构来维护贡献,然后注意操作的时间顺序就可以了。
模板题:K大数查询,Dynamic Rankings,可以看蓝书。
线段树分治
和\(cdq\)分治一样,是时间分治的一种。
就是对时间建线段树,然后把一个时间段内存在的操作打在线段树的\(log\)个区间节点上。而对于一个时间点的询问,就对应了线段树的一个叶节点,所以只需将询问挂在叶节点上即可。
在线段树上处理完所有操作和询问后,对整棵线段树\(dfs\)一次,向下访问时依次处理掉节点上的操作,到达叶节点就回答掉询问,向上回溯时就撤销掉操作。
别的都很简单啊,想好用什么数据结构维护操作(要支持撤销)即可。
后缀数组
实际上是后缀排序,只学了\(O(nlog_2n)\)倍增法。
其实倍增就体现在排序的长度上,每一次排序只根据每个后缀的前二的幂次为来排一个相对位置,在\(O(log_2n)\)次排序后就能得到最后的排名。
每一次当中如何排序呢?用双关键字的基数排序,时间复杂度的\(O(n)\)的。我们取\((rank1_i,rank2_i)\)作为排序的双关键字,\(rank1_i\)指的是后缀\(i\)上一次排序后的排名,而\(rank2_i\)指的是后半部分后缀上一次排序后的排名,相当于倍增\(2^k\)过程中一个管辖前\(2^{k-1}\)个字符,一个管辖后\(2^{k-1}\)个字符。
如果是\(sort\)的话,这样就已经可以了,但是时间复杂度是\(O(nlog^2n)\)。
基数排序如何实现?我们还得记一下\(pos_i\):第二关键字排名为\(i\)的后缀位置。这样就可以在基数排序的时候定位第二关键字了。
\(height\)数组怎么求,最重要的性质就是\(height[rank[i]]\geq height[rank[i-1]]-1\),然后就可以利用单调性求了。
后缀数组好像有很多经典的运用,还没有学完。
快速傅里叶变换
最直接的运用就是计算多项式乘法。
很简单的思路,系数表达法做乘法太慢,就用点值表达法做乘法。于是想办法搞一个算法可以在\(O(nlog_2n)\)的时间内在系数和点值之间做转换,就是\(FFT\)在做的事情。
思路是分治,\(n\)个点我们带入\(n\)个不同的单位根,我们发现当对多项式根据次数奇偶性分类后,可以计算一半得到另一半的值,于是就能递归下去了。
最后的优化就是把递归省了,发现可以用二进制的\(bit-reverse\)来搞。
快速数论变换
发现把\(FFT\)的单位根换成原根,折半引理和消去引理照样成立,于是就有了模意义下的\(FFT\)。
分治FFT
要算一个卷积,但是发现卷积计算式中有一项和我们未计算的值有关。
于是可以想到\(cdq\)分治,每一次尝试计算左边对右边的贡献即可。计算贡献时,发现还是一个卷积,\(NTT/FFT\)即可。
Edmonds-Karp增广路
求网络最大流。
先是\(FF\)算法的思想,找到一条增广路就增广。但是这样时间复杂度是不对的,上限可达\(O(m|f_{max}|)\)。
可以证明,每次找最短路径增广路,增广次数不会超过\(O(nm)\)次,然后\(EK\)增广路就诞生了。
模板题这里,博客已经写了。
dinic算法
\(EK\)增广路的优化。
多数时候最短路径增广路不止一条,于是就能想到多路同时增广。实现的时候还要加上若干剪枝,就可以证明时间复杂度是\(O(n^2m)\)的\(dinic\)算法了。
模板题这里,博客已经写了。
费用流
没什么意思,把最大流的最短路径增广路用用最短路算法跑一下就可以了。
一般来说直接\(SPFA\)即可,加个\(johnson\)算法的势函数优化也可以用\(dijkstra\)。
还有一种思路就是学\(KM\)算法的改顶标,只需满足三角形不等式即可。这样的\(zkw\)费用流在稠密图上效率比较高,就是不能跑负权图(最大费用最大流)。
2-sat模型
就是考虑命题之间的推导关系,在图上连的是有向边,当然逆否命题之间也要连边。
然后考虑矛盾性,只要用\(tarjan\) \(SCC\)缩点即可。如果要输出一组可行解,只需自底向上执行拓扑排序即可。当然,利用\(tarjan\)的性质可以很方便的写出代码。
看蓝书吧。
二分图
先是二分图判定,可以用染色法,不断给相邻节点标不同的颜色,然后看一看哟没有冲突即可。
二分图匹配,可以直接跑最大流,或者用匈牙利算法。匈牙利算法的本质就是不断找增广路,找到了就对路径上的边取一下反,这样最大匹配的大小就会增加\(1\)。
二分图带权匹配,可以直接跑费用流,也可以用\(KM\)算法。\(KM\)算法的思路就是通过合法修改顶标的手段不断扩大相等子图。不过,\(KM\)算法只有在带权最大匹配是完备匹配时才能用。
Link-Cut-Tree
要维护一棵树的链信息,需要支持动态加边,删边。
方法是链剖,不过是实链剖分,要用一堆\(splay\)来维护。核心操作是\(access\),如何理解?虚实链其实是自己定义的,我们只要维护好打通一条实链的正确\(splay\)森林即可,这样链信息就是可以正确维护的,并且时间复杂度是\(O(log_2n)\)。
操作有点多,但是码量不大,需要注意一些细节,在完成代价为树高的操作时别忘了\(splay\)一下保证时间复杂度。
后缀自动机
一个很鬼畜的自动机,\(endpos\)等价类维护成一个状态,字符维护成转移,再加一些后缀链接就以高度压缩的形式维护了一个字符串的所有子串信息。
难点在于构建,其实核心就是那三种情况的分类讨论。而最难理解的就是第三种情况,其实\(clone\)一个点的本质就是一个\(endpos\)等价类的两个子串一个不属于同一个\(endpos\)等价类了,必须分裂一个状态才能正确地维护后缀链接。
用法好像有很多,还是很会,但是代码挺短的。
杜教筛
求积性函数的前缀和。
没啥神奇的,就是对一个函数做一下狄利克雷卷积,发现推出了一个子问题,还可以用整除分块来做,于是就变成了记忆化搜索。
可以用线性筛先预处理一些值,然后再记忆化搜索时间复杂度就是\(O(n^{\frac{2}{3}})\)的。
杜教筛的时间复杂度瓶颈是整除分块,所以求狄利克雷卷积的另外两个数论函数的时间复杂度要求是根号的,不一定要\(O(1)\),甚至还可以套杜教筛。
模板题这里,可以看\(R\)爷课件。
Miller-Rabin 算法
素性判定的\(RP\)算法,时间复杂度\(O(log_2n)\)。
两个步骤,费马小定理和二次探测定理,没什么好说的,当取\(10\)个质数的时候出错率几乎为\(0\)。
Pollards'Rho 算法
基于\(Miller-Rabin\)的质因子分解算法,期望复杂度\(O(\sqrt[4]{n}log_2n)\)。
原理其实是基于生日悖论,每次用两个随机数的差尝试分解成功概率更大。而随机数的生产就是用\(x_i=x_{i-1}^2+c\)的形式,保证分布均匀。
随机数可能尝试模意义下的环,就用倍增标记的方法判就可以了。
模板题这里。
『2019Summer Algorithms』的更多相关文章
- 似魔鬼的 『 document.write 』
在平时的工作中,楼主很少用 document.write 方法,一直觉得 document.write 是个危险的方法.楼主不用,并不代表别人不用,最近给维护的项目添了一点代码,更加深了我对 &quo ...
- 拾遗:『Linux Capability』
『Linux Capability』 For the purpose of performing permission checks, traditional UNIX implementations ...
- 『创意欣赏』20款精致的 iOS7 APP 图标设计
这篇文章给大家分享20款精致的 iOS7 移动应用程序图标,遵循图形设计的现代潮流,所有图标都非常了不起,给人惊喜.通过学习这些移动应用程序图标,设计人员可以提高他们的创作,使移动用户界面看起来更有趣 ...
- 『设计前沿』14款精致的国外 iOS7 图标设计示例
每天都有大量的应用程序发布到 iOS App Store 上,在数量巨大的应用中想要引起用户的主要,首要的就是独特的图标设计.这篇文章收集了14款精致的国外 iOS7 图标设计示例,希望能带给你设计灵 ...
- Github 恶搞教程(一起『玩坏』自己的 Github 吧)
最近在伯乐在线读到一篇趣文,<如何在 Github『正确』做贡献>,里面各种能人恶搞 Github 的『Public contributions』,下面截取几个小伙伴的战绩: 顺藤摸瓜,发 ...
- 『创意欣赏』30幅逼真的 3D 虚拟现实环境呈现
又到周末了,给大家分享30幅漂亮的 3D 虚拟现实环境呈现,放松一下.这些创造性的场景都是通过 3D 图形设计软件,结合三维现实环境渲染制作出来的.一起欣赏:) 您可能感兴趣的相关文章 20幅温馨浪漫 ...
- [TYVJ1827]『Citric II』一道防AK好题
时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 第二届『Citric杯』NOIP提高组模拟赛第一题 描述 Lemon认为在第一届『Citric』杯模拟赛中出的 ...
- 办理滑铁卢大学(本科)学历认证『微信171922772』UW学位证成绩单使馆认证University of Waterloo
办理滑铁卢大学(本科)学历认证『微信171922772』UW学位证成绩单使馆认证University of Waterloo QQ/微信171922772办理毕业证成绩单.真实使馆及教育部学历认证★诚 ...
- 办理渥太华大学(本科)学历认证『微信171922772』Ottawa U学位证成绩单使馆认证University of Ottawa
办理渥太华大学(本科)学历认证『微信171922772』Ottawa U学位证成绩单使馆认证University of Ottawa QQ/微信171922772办理毕业证成绩单.真实使馆及教育部学历 ...
随机推荐
- qtcreator VLD内存检测
简介 Visual Leak Detector是一款用于Visual C++的免费的内存泄露检测工具.相比较其它的内存泄露检测工具,它在检测到内存泄漏的同时,还具有如下特点: 可以得到内存泄漏点的调用 ...
- PTA 根据后序中序遍历输出先序遍历
本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果. 输入格式: 第一行给出正整数N(≤30),是树中结点的个数.随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果, ...
- APIO2019游记
Day -n~Day -2 文化课好难啊.. Day -1~Day 0 颓颓颓 Day 1 人生第一次用Linux 根本不会 早上刚学会怎么编译 不到1h就上考场实战了 开始之后写了读优 一直编译失败 ...
- serialize()和new FormData()的区别
serialize()和FormData对象都可将表单数据序列化,后通过ajax异步提交 ,序列化表单就是将form表单中所有name属性序列化成KEY-VALUE的形式,提交到后台,后台以对象相应的 ...
- Windbg Scratch Pad(便笺簿)窗口的使用
“便笺簿”窗口是一个剪贴板,您可以在其中键入和保存文本. 打开便笺簿 通过菜单View--->Scratch Pad 通过快捷键Alt+8 通过工具栏 使用便笺簿 用上面的方式打开的窗口如下: ...
- docker的简单操作和端口映射
一:简介 Docker镜像 在Docker中容器是基于镜像启动的 镜像是启动容器的核心 镜像采用分层设计,最顶层为读写层 使用快照COW技术,确保底层不丢失 通过ifconfig(ip a)来查看d ...
- ESA2GJK1DH1K基础篇: 测试APP使用SmartConfig绑定Wi-Fi 设备并控制设备
前言 实现功能概要 STM32控制WI-Fi模块以AT指令TCP透传方式连接MQTT服务器, 实现MQTT通信控制. 测试准备工作(详细下载步骤请参考 硬件使用说明 ) 一,下载单片机程序 二,安装A ...
- Computer-Hunters——项目需求分析
Computer-Hunters--项目需求分析 前言 本次作业属于2019秋福大软件工程实践Z班 本次作业要求 团队名称: Computer-Hunters 本次作业目标:撰写一份针对团队项目的需求 ...
- 超强在线考试系统源码(私有部署&二次开发)
随着信息化技术的发展,考试系统也在进行着深入的变革.从传统的纸质考试人工评分到现在的在线考试自动评分. 在线考试系统的应用场景也在逐渐扩宽,例如:学校的学生考试.员工培训考试.招聘考试.职称考试等等. ...
- 【技术博客】Django中文件下载的实现
开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了.我们认为这样的经验是有必要记录下来的,因此就有了[技术博客]. Django中文件下载的实现 1.背景 在VisualPy ...