2024.4.6 - 4.12
Sat
JOI 2023 Final
宣传 2
\(n\) 个人,每个人有住所位置 \(X_i\) 与影响力 \(E_i\),一个人 \(i\) 拿到书后会号召另一个人 \(j\) 买书仅当 \(|X_i-X_j|\leq E_i - E_j\),你最少送多少个人书才能使得所有人都会有书(送的或者被号召买书)。
\(n\leq 5\times 10^5\)。
拆一下绝对值,得:
设每个人为点 \(P_i(E_i - X_i, E_i + X_i)\),如果有一个点在另一个点左下角那么就会被号召。
按照 \(x\) 排序,单调栈算有几个点不被号召即可。
迷宫
给定一个 \(R\times C\) 的迷宫,每次操作可以选择一个 \(N\times N\) 的子矩阵并抹除该部分的所有障碍,求最少操作次数使得可以从起点到终点。
\(R\times C\leq 6\times 10^6, N\leq R\leq C\)。
首先显然要 01bfs,如果可以从路走就从路走。
考虑暴力更新,时间复杂度为 \(\mathcal{O}(RCN^2)\)。
可以发现,每一个格子通过一次操作所得到的行动范围是一个 \((2N+1)\times (2N+1)\) 的矩形,挖掉四个角。如果终点不在内部,则需要跨出边界。
维护边界即可,暴力扫的时间复杂度为 \(\mathcal{O}(RCN)\),此处 \(N\) 同阶于 \(\mathcal{O}(\sqrt{RC})\)。
拿一个并查集维护,时间复杂度为 \(\mathcal{O}(RC\alpha(R))\)。
训猫
\(n\) 个点的树,每个节点有一个高度 \(P_i\),构成全排列。
每一次你可以标记一个点,如果标记到猫所在的点,猫会到达【最高的】【可以不通过被标记的点到达的】点。
猫初始在高度为 \(n\) 的点,请问合理的标记顺序可以让猫最多走多远?
\(n\leq 2\times 10^5\)。
考虑 DP,发现每次删掉一个点后会到达一棵子树并且无法返回,记 \(f_u\) 表示猫在 \(u\) 点,最多可以走的距离,则显然从每个子树中编号最大的点 \(v\) 转移 \(f_v + dis(u,v)\)。
考虑按照高度从小到大枚举转移,直接用高度建边,并用并查集维护连通性即可。
现代机器
待补。
ABC348
A. 循环结构+分支结构。
B. 循环结构+分支结构+取max。
C. 按颜色排序可以处理。
D. bfs。
E. 换根DP。
F. bitset。
G. 分治问题,不会做。
Sun
最小路径覆盖问题
超源向出度连接,超汇向入度连接,走一条匹配边表示将该边加入路径集合。
考虑走向超汇之后继续从超源出发向对应点完成一条路径。
向入度连接,表示从该位置出发,如果从某点出发有代价需要以此方式连接,没有权值可以不按照此方式,但是会略显抽象。
餐巾计划问题中早上对应右部点(入度),晚上对应左部点(出度)。
修车
【SCOI2007】
\(m\) 个人修 \(n\) 辆车,每人一次只能修一辆车,每个人修每辆车有 \(T_{i,j}\) 的时间花费,求在合适的安排下,所有人等待的最短总时间。
\(m\leq 9, n\leq 60\)。
拆点,将每个人拆成 \(n\) 个状态,表示修了这么多车。
每个人的每个状态的容量是 \(1\),可以向每辆车连,花费是 \(T_{i,j}\times k\),此处 \(k\) 表示这是第 \(k\) 辆车。
每辆车的容量是 \(1\),表示只被修一次。
无论你找出了什么贪心策略,最小费用最大流总是保证费用最优。
美食节
【NOI2012】
\(n\) 个菜品,第 \(i\) 个菜品的需求量为 \(p_i\),以及 \(m\) 个厨师,每个厨师可以在同一时刻做一份单人分量的菜。
求所有人等待的最短总时间。
\(n\leq 40, m\leq 100, \sum p_i\leq 800\)。
问题很像修车,首先改掉每一道菜的容量。
然后发现边数巨大,需要动态加点,加边。
每增广一个厨师做一道菜后,再为这个厨师开一个新点继续跑最小费用最大流。
二分图再探
搭配飞行员
\(m\) 个正驾驶员和 \(n\) 个副驾驶员,已知一些飞行员组合(一正一副),求最多的飞行员组合,两组之间互不相交。
\(m+n\leq 100\)。
这是二分图,所以做二分图最大匹配。
Courses
【ZJU1140】
\(n\) 个学生修 \(m\) 门课,对于每门课你需要找出一个修该课的学生,请问是否存在一种方式使得:
- 每个学生最多被选出一次。
- 每门课都可以选出一个学生。
\(m\leq 100, n\leq 300\)。
二分图最大匹配判定。
Asteroids
【USACO05NOV Gold】
\(m\times m\) 二维平面上有 \(n\) 个陨石,每次你可以选择一条平行于坐标轴的直线并清除上面的所有陨石,请问最少操作次数。
\(m\leq 500\)。
横坐标为左部点,纵坐标为右部点,则最小点覆盖为所求。
舞会
【SHOI2002】
\(m\) 个男生与 \(n\) 个女生,其中若干对异性跳过交谊舞,现邀请一些学生,使得两两之间没有跳过舞,问最多邀请的学生数。
\(m+n\leq 1000\)。
男女生分别为左部点与右部点,则最大独立集为所求。
Place the Robots
【ZJU1654】
一个 \(n\times m\) 的地图中,有墙、草地、空地,只有空地可以放置机器人,【没有被墙隔开的】【位于相同行或列】的两个位置不能同时放机器人,问最多放多少机器人。
\(n,m\leq 50\)。
首先对每一行与每一列求出极长的不被墙阻隔的块,则:
行的极长块编号为左部点,列的极长块编号为右部点,则最大匹配为所求。
棋盘覆盖
给定一个带有障碍的 \(n\times n\) 的棋盘,请问最多用多少个 \(1\times 2\) 或 \(2\times 1\) 的骨牌覆盖。
\(n\leq 100\)。
将坐标 \((i,j)\) 按照 \(i+j\) 的奇偶性分类,奇数的为左部点,偶数的为右部点,则最大匹配为所求。
采集标本
给定一张 \(n\) 个点的 DAG,求该图的最小路径覆盖。
\(n\leq 200\)。
让 \(u\) 匹配 \(v\) 表示将 \(u\to v\) 加入路径集合中,则最大匹配表示最多的合并次数。
初始为 \(n\) 个单点构成 \(n\) 条路径,所以答案为 $n- $最大匹配。
线段相交
给定水平或垂直的 \(n\) 条线段,选出最多的线段,使得它们两两不交。
保证:两条水平的线段或者两条垂直的线段不会相交。
\(n\leq 2000\)。
水平线段为左部点,垂直线段为右部点,相交则连边,此图构成二分图。
则最大独立集为所求。
Machine Schedule
【ZJU1364】
两台机器分别有 \([0,n)\) 与 \([0,m)\) 的工作档,初始均为 \(0\) 档,有 \(k\) 个任务,每个任务要求用机器 A 的 \(x\) 档或机器 B 的 \(y\) 档完成,换挡则需要重启。
求最少换挡次数完成所有任务(可以不按顺序)。
\(n,m < 100, k < 1000\)。
\(x\to y\) 连边构成二分图(分别属于左部点与右部点),不考虑 \(0\) 号点,则最小点覆盖为所求。
Muddy Fields
【USACO05JAN Gold】
给定一个 \(n\times m\) 的地,某些地是草地,其它是泥沼,一块木板可以覆盖一行或者一列中连续的一部分,木板间可以重叠,求最少耗费的木板数量覆盖所有泥沼,不能覆盖草地。
\(n,m\leq 50\)。
首先对每一行与每一列求出极长的不被墙阻隔的块,则:
行的极长块编号为左部点,列的极长块编号为右部点,则最小点覆盖为所求。
Pair
【2017 山东一轮集训 Day2】
给定两个序列 \(a,b\),长度分别为 \(n,m\),对 \(a\) 中每一个长度为 \(m\) 的连续子序列 \(c\),判断 \(c\) 与 \(b\) 是否匹配。
我们称两个长度相等的序列匹配,当且仅当两个序列中的元素可以两两配对,我们称两个数 \(x,y\) 配对,当且仅当 \(x+y\ge h\),其中 \(h\) 为给定常数。
换句话说,称长度为 \(k\) 的两个序列 \(X,Y\) 匹配,当且仅当存在一个 \(k\) 的全排列 \(P\),使得 \(\forall 1\leq l\leq k, X_l + Y_{P_l}\ge h\)。
\(m\leq n\leq 1.5\times 10^5\)。
若 \(X_i + Y_j\ge h\),则称 \(i,j\) 之间有边,两个序列匹配仅当该二分图有完美匹配。
根据 Hall 定理,有 \(\forall S, |N(S)|\ge |S|\)。
对于每一个 \(a_i\),可以很容易的求出有多少个 \(j\) 满足 \(a_i + b_j\ge h\),后文称为匹配数量,这也是 \(N(\{i\})\) 的大小。
按照 \(a_i\) 升序考虑,则一段前缀的 \(a_i\) 匹配一段后缀的 \(b_i\),要求:
- \(\forall 0\leq i\leq m\),匹配数量不超过 \(i\) 的元素数量总和不超过 \(i\)。
不妨记 \(g_i\) 表示区间中匹配数量恰好为 \(i\) 的数的个数,则:
- \(\forall 0\leq i\leq m, \overset{i}{\underset{j=0}{\sum}} g_j \leq i\),可以得到 \(\forall 0\leq i\leq m, \overset{i}{\underset{j=0}{\sum}} g_j-1 < 0\)。
线段树维护即可。
Mon
LYZ-Ice Skates
【POI2009】
\(n\) 种尺码的鞋子各 \(k\) 双,脚的大小为 \(x\) 的人可以穿尺码在 \([x,x+d]\) 范围内的鞋子,接下来 \(m\) 个操作,每个操作形如脚大小为 \(r\) 的人多了 \(y\) 个(\(y< 0\) 表示减少了 \(-y\) 个),请问每个操作后,是否每个人都能穿合适的鞋子。
脚大小在 \([l,r]\) 内的一些人构成的限制 \(|N(S)|\ge |S|\) 最为严格,记 \(g_i\) 表示当前脚大小为 \(i\) 的人的数量,考虑限制的表达式:
- \(\overset{r}{\underset{i=l}{\sum}} g_i\leq (r-l+1+d)k\),可以得到 \(\overset{r}{\underset{i=l}{\sum}} g_i-k \leq dk\)。
这需要求出最大子序列之和,要求不大于 \(dk\)。
线段树维护即可。
毕业旅行
【Violet 4】
给定一张 DAG,要求选出最多数量的点,使得两两之间无法到达。
\(n\leq 200\)。
根据定义,即求最长反链。
相关表达式
对于二分图:
- 最大匹配 = 最小点覆盖
- 最大独立集 = \(n-\)最小点覆盖。
对于 DAG:
- 最小路径覆盖 = \(n-\)对应二分图的最大匹配。
- 最长反链 = 最小链覆盖 = \(n-\)传递闭包后对应二分图的最大匹配。
Trash
【ural1076】
\(n\) 个垃圾桶内有 \(n\) 种垃圾,第 \(i\) 个垃圾桶内有第 \(j\) 种垃圾共 \(a_{i,j}\) 的量,将一单位垃圾从一个垃圾桶放到另一个垃圾桶需要 \(1\) 的代价,求垃圾分类的最少代价。
\(n\leq 150\)。
最大权匹配表示最多可以保留多少的代价,则最小代价易求。
祭祀
【CTSC2008】
给定一张 DAG,求最长反链大小,并给出一组合法方案,判断每个点是否在某个最长反链上。
\(n\leq 100\)。
首先最长反链好求,判断每个点是否在某个最长反链上也好做,强制选定这个点判断最长反链大小是否减一。
如何给出合法方案?
考察转为二分图 \(H\) 后,跑出最大匹配,从左部点中一个未匹配点开始 dfs,取左部未被 dfs 的点、右部被 dfs 的点构成点集 \(S\),则 \(S\) 是 \(H\) 的最小点覆盖。
证明:
- \(S\) 的大小等于最大匹配的大小。
- 在左侧选择的一定是匹配点,左侧的某个匹配点未被选中仅当匹配的右部点被选中,每条匹配上恰好会选中一个点,右侧的非匹配点不会被 dfs,否则与最大匹配矛盾。
- \(S\) 覆盖所有边。
- 考虑将边分成【左/右】部点【是/否】被 dfs 分成 \(4\) 类,若一条边没有被覆盖,仅当左端点被 dfs 到而右端点没有,而该情况不可能存在,矛盾。
\(S\) 的补集为一最大独立集,记为 \(I\),记拆点后两端均在 \(H\) 中的点为 \(T\),则 \(T\) 为最长反链。
证明:
- \(T\) 为一反链。
- 如果其中存在一对点 \(x\) 与 \(x'\)(一个点拆出来的)使得其不构成反链,仅当 \(x\) 与 \(x'\) 有边,这与 dfs 过程矛盾。
- \(T\) 是最长反链。
- \(|I| = 2n - |S|\),且 \(I \setminus T\) 可以看作是 \(x\) 与 \(x'\) 恰有一端属于 \(I\),那么有 \(|I\setminus T|\leq n\),所以 \(|T|\ge n - |S|\),且无法达到更大,故 \(T\) 是最长的。
于是选出左部点被选,右部点未选的点构成反链即可。
Tue
Soldier and Traveling
【CF546E】
\(n\) 个人,初始城市 \(i\) 有 \(a_i\) 人,要求变为 \(b_i\) 人,每座城市上的人最多走到相邻的城市,或者不走,请问是否能达成目标,并给出方案。
\(n\leq 100\)。
跑一遍最大流,有解要求所有与源点、汇点相连的边满流,方案看中间连的边。
Minimal k-covering
【CF976F】
给定一个二分图 \(G=(L,R,E)\),记 \(D_{\min}\) 表示图中点度数的最小值,要求 \(\forall k\in [0,D_{\min}]\),求出一个 \(E'\subseteq E\),满足:
- 所有顶点都至少被 \(k\) 条边覆盖。
- \(|E'|\) 是最小的。
并输出方案。
\(|L|,|R|,|E|\leq 2000\)。
记每个点的度数是 \(d_i\),至少被 \(k\) 条边覆盖等价于至多 \(d_i - k\) 条边不被选中,\(|E'|\) 是最小的等价于 \(|E\setminus E'|\) 最大,跑最大流,满流边表示不选。
Goods transportation
【CF724E】
\(n\) 座城市,每一座城市的产出为 \(p_i\),销售上限是 \(s_i\),对于所有 \(i < j\) 都有 \(i\to j\) 可以运送最多 \(c\) 的货物,可以沿着一些道路一路运送,问最多销售的货物数量。
\(n\leq 10^4\)。
考虑建立最大流,超源向每个点连容量是 \(p_i\),超汇向每个点连容量是 \(s_i\),每个点往后面的容量都是 \(c\)。
但是边数巨大,考虑模拟网络流。
根据最大流最小割定理,考虑计算最小割。
根据最小割的定义,记 \(S\) 表示选择割 \(p_i\) 的点的点集,则有:
如果选择对一个点同时割 \(p_i,s_i\),那么可以发现这个 \(p_i\) 如割,不割只会使得代价减少,而割去的 \(c\) 边不变。
考虑 DP,记 \(f_{i,j}\) 表示前 \(i\) 个点有 \(j\) 个不属于 \(S\),则转移显然。
时间复杂度为 \(\mathcal{O}(n^2)\)。
网络流相关
太空飞行计划
\(m\) 个实验以及 \(n\) 个仪器,每个仪器有花费,每个实验有收益以及依赖的仪器,求最大收益。
\(m,n\leq 50\)。
最大权闭合子图。
超源连实验,超汇连仪器,实验连依赖的仪器,割掉实验表示不做这个实验,割掉仪器表示购买这个仪器。
即可求出最小损失。
最大获利
【NOI2006】
\(n\) 个中转站,建造中转站 \(i\) 的花费是 \(a_i\),\(m\) 个用户群,第 \(i\) 个用户群需要中转站 \(a_i,b_i\),收益为 \(c_i\),求最大收益。
\(n\leq 5000, m\leq 50000\)。
超源连用户群,用户群连所需中转站,中转站连汇点,割掉用户群表示不拿这个群的收益,割掉中转站表示建造该中转站。
即可求出最小损失。
电影迷
【TJOI2010】
\(n\) 场电影,看每场电影的体验值是 \(a_i\)(可正可负),\(m\) 条限制,每条限制声明如果看电影 \(a_i\) 而不看电影 \(b_i\),则体验值减少 \(w_i\),求最高体验值。
\(n\leq 100\)。
首先,电影连源点或汇点依赖于其体验值的正负性,正的连源点,负的连汇点,限制则从 \(a_i\) 向 \(b_i\) 连 \(w_i\),割掉表示不满足该限制。
最小割求出最小损失。
Order
【CEOI2008】
\(n\) 个工作,\(m\) 个机器,每个工作有收益,并分为若干工序,每一个工序需要 \(a_i\) 机器,在该工序中租用该机器的花费是 \(b_i\),买下一台机器 \(i\) 的花费是 \(c_i\),求最大收益。
每台机器只要买下就可以在后面所有需要该机器的工序派上用场。
\(n,m\leq 1200\)。
超源连工作,超汇连机器,对于每一个工作,向对应的机器连租用费用的边,割掉表示租用。
即可求出最小损失。
最优标号
给定一张图 \(G\),\(G\) 中每条边的权值是两端点点权的异或,已知其中部分点的点权,求最小边权和。
\(|V|\leq 500, |E|\leq 3000\),已知点权小于 \(2^{31}\) 且非负。
根据位运算的性质,各位独立,我们可以对每一位分别求解。
也可以发现,如果一条边两端点点权都没有限制,那么这条边的权值可以为 \(0\)。
于是,每个已知点权的点都向源点、汇点连边,根据该点权在特定位上的值,向其中一边连权值为 \(0\) 的边,另一边权值为正无穷。
边的部分参考善意的投票,两边互连边权为 \(1\) 的边,表示其中一个端点要求另一个端点的位与自己一致。
求出最小割即可得到该位的 \(1\) 的最少数量,对每一位分别求解即可。
Network Wars
【ZOJ2676】
给定一张服务器通讯网,若干条光缆双向连接服务器,控制该光缆有成本,控制一些光缆使得服务器 \(1\) 到服务器 \(n\) 的所有可能的数据传输路线上都至少有一条光缆被控制,最小化控制的光缆平均成本,并给出方案。
\(n\leq 100\)。
01分数规划加最小割,假设当前要 check 的值是 \(v\),一条光缆的成本变为 \(w - v\),所有负价光缆应当全部选中,而正价光缆跑一遍最小割即可。
最终的方案就是最小割的方案加上所有负价光缆。
Hard Life
【NEERC2006】
给定 \(n\) 个人以及 \(m\) 条死对头关系,定义一种选人集合 \(S\) 的麻烦度为选人包含的死对头关系除以选择人数,求最大麻烦度时的最大选人数量。
\(n\leq 100, m\leq 1000\)。
考虑二分值 \(v\) 并 check,选择一个人的代价是 \(v\),选择一对关系的收益是 \(1\),考虑最大权闭合子图。
本题卡精度,设 eps 为 \(10^{-8}\) 可过,设为 \(0.1\) 也能过……
最终选择人数是残量网络上可达点。
Wed
Toy Machine
【CF1817D】
给定一张 \(2\times n\) 的网格图,保证 \(n\) 为奇数,其中 \((2,1),(2,n),(2,\frac{n+1}{2})\) 位置是障碍物。
有 \(n-2\) 个方块,第 \(i\) 个方块的位置是 \((1,i+1)\)。
你需要构建一个操作序列 \(S\),包含字符 LDRU
,对于一种操作,将网格图往此面倾斜,最终状态是重力影响下每个方块的最终位置。
目标:将原始状态下第 \(k\) 个方块移动到 \((1,1)\) 位置。
\(n\leq 10^5, k\leq n-2\),要求 \(|S|\leq 10^6\)。
神奇构造题。
首先目标方块在正中间时是简单的,DL
搞定。
如果目标方块在左半部分(正中间也可以),发现 LDRU
可以将最左边的方块的编号加一。
初始第一个方块在左边,一次 LDRU
操作后就变成第二个方块在最左边,将目标方块移动到最左边后,接一个 L
完成。
如果目标方块在右半部分,我们可以类似的把目标方块移动到最右边,然后发现不断使用 RDRU
可以将所有方块集中在右半部分,然后进行多次 LDRU
操作就可以把目标方块移动到最左边,接一个 L
完成。
Binary Table
【CF662C】
给定一个 \(n\times m\) 的 \(01\) 网格图,每次可以取反一行或一列,求网格图上 \(1\) 的最少数量。
\(n\leq 20, m\leq 10^5\)。
一个非常暴力的算法:
枚举行的转换方式,然后对每一列决定取反还是不取反。
这启发我们对正解的思考。
考虑记 \(c_i\) 表示列状态为 \(i\) 的出现次数,记 \(m_i\) 表示状态为 \(i\) 时取反与不取反 \(1\) 数量的较小值。
那么,如果行的转换方式为 \(t\),则答案的式子可以表示为 \(f_t = \overset{2^n-1}{\underset{i=0}{\sum}} c_i\times m_{i\oplus t}\)。
换句话说,有 \(f_i = \underset{j\oplus k = i}{\sum} c_j\times m_k\),做 FWT 即可。
洪水
给定一棵 \(n\) 个节点的树,节点 \(1\) 为根,每个节点都有一个点权 \(w_i\),给出 \(m\) 个操作,要么增加一个点的点权,要么给出子树的根 \(x\) 做以下问题:
- 选出一些节点,代价是所选点的点权总和,要求最小化代价且满足 \(x\) 【在不通过选中点的情况下】到达任意叶子节点。
\(n,m\leq 2\times 10^5\)。
考虑 DP,记 \(f_i\) 表示在以 \(i\) 为根的子树下通过选中节点使得 \(i\) 到所有叶子节点不连通的最小代价,有:
考虑树上 DDP,分离轻重儿子,记 \(g_i = \underset{j\in to_i \land j \ne h_i}{\sum} f_j\),则对于所有非叶子节点有 \(f_i = \min(w_i, g_i + f_{h_i})\),为了方便,对于所有叶子节点有 \(g_i = +\infty\)。
考虑矩阵转移式,定义广义矩阵乘法运算为 \((\min,+)\) 则有:
树剖维护即可。
Thur
KMP 相关
Oulipo & 子串查找
【POJ3461】
给定两个字符串 \(A,B\),求 \(B\) 在 \(A\) 中的出现次数。
\(1\leq |B|\leq |A|\leq 10^6\)。
KMP 模板。
Power Strings
【POJ2406】
给定一个字符串 \(S\),求 \(S\) 的最短完整循环节的出现次数。
\(1\leq |S|\leq 10^6\)。
首先,\(\text{nxt}_n\) 表示全串的最长真 Border 的长度,\(n-\text{nxt}_n\) 表示最长循环节长度。
如果不整除,则此时没有完整循环节,输出 1
。
Period
给定一个字符串 \(S\),对每个 \(S\) 的前缀 \(P_i\) 求最短完整循环节的出现次数,仅输出出现次数 \(>1\) 的。
\(1\leq |S|\leq 10^6\)。
套用上面的结论即可。
Milking Grid
【USACO2003】
给定一个字符矩阵 \(M\),求 \(M\) 最短的循环子矩阵 \(N\),即求出一个最小的子矩阵 \(N\),使得这个子矩阵的无限复制扩张之后的矩阵包含 \(M\)。
\(1\leq R\leq 10^4, 1\leq C\leq 75\)。
类似的,我们对横向和竖向都做 KMP,并且令 \(\text{nxt}_i\) 表示到第 \(i\) 行/列的最长公共前后缀(为一个字符矩阵)。
两个维度是独立的,分别求出最小值然后乘一下。
Seek the Name, Seek the Fame
求 \(S\) 的所有 Border 的长度。
\(1\leq |S|\leq 10^6\)。
首先原串是其本身的 Border,然后找到其最长真 Border,这也是原串的 Border,该 Border 的最长真 Border 依旧是原串的 Border,也就是 \(\text{nxt}\) 树构成的一条从根到 \(n\) 号点的链,不断跳 \(\text{nxt}\) 即可。
String & 前缀和
求 \(S\) 的所有前缀在 \(S\) 中的出现次数。
\(1\leq |S|\leq 10^6\)。
根据 \(\text{nxt}\) 数组构造 \(\text{fail}\) 树,每一个节点都是原串的一个前缀,该前缀的出现次数就是以它为根的子树大小,倒序 DP 即可。
OKR-Periods of Words
【POI2006】
我们定义 \(Q\) 是 \(a\) 的周期仅当 \(Q\) 是 \(a\) 的真前缀且 \(a\) 是 \(Q+Q\) 的前缀,对 \(S\) 的每一个前缀求其最长周期的长度之和。
\(1\leq |S|\leq 10^6\)。
原题等价于求 \(S\) 的每一个前缀的最短 Border,记忆化跳 \(\text{nxt}\) 数组即可。
对于一个字符串 \(S\),如果其有 Border,那么总是可以证明存在一个大小不大于其长度一半的 Border。
动物园
【NOI2014】
对 \(S\) 的每一个前缀求所有长度不大于其长度一半的 Border 的数量。
\(1\leq |S|\leq 10^6\)。
不考虑长度要求,我们可以在 KMP 的过程中递推每个前缀的 Border 数量。
再一次进行 KMP,此时直接求解题目所问的数量,如果长度超过其限制也跳 \(\text{nxt}\) 即可,为了让时间复杂度正确,对于前一个位置的指针位置保留到下一个指针。
时间复杂度为 \(\mathcal{O}(|S|)\)。
Censoring
【USACO2015Feb Silver】
给定两个字符串 \(S,T\),每次删去 \(S\) 中最早出现的那个 \(T\),然后把前后两段按照顺序视为新的 \(S\),问最终的 \(S\)。
\(1\leq |T|\leq |S|\leq 10^6\)。
匹配的时候加一个栈,每次匹配成功后弹出栈最上方的 \(|T|\) 个元素,同时记录每个 \(S_i\) 的最大匹配位置是多少。
最终存储在栈内的元素按照自底向上的顺序即为最终的 \(S\)。
Prefixes and Suffixes
【CF432D】
求 \(S\) 的所有 Border 在 \(S\) 中的出现次数。
\(1\leq |S|\leq 10^5\)。
等价于,求 \(S\) 的所有 Border 套上每个前缀的出现次数。
似乎在梦中见过的样子
求 \(S\) 中所有可以以 \(A+B+A\) 的形式划分的子串的数量,其中 \(|A|\ge k, |B|\ge 1\)。
\(1\leq |S|\leq 1.5\times 10^4\)。
首先注意到有一个 \(A+B+A\) 的形式且 \(|A|\ge k\),这说明 \(A\) 的长度严格小于其一半且尽量长,我们直接沿用【动物园】的做法,就可以对每一个前缀求出是否满足条件。
我们可以暴力枚举 \(S\) 的每一个后缀跑 KMP,即可求出答案。
时间复杂度为 \(\mathcal{O}(|S|^2)\)。
字符串大师
【Lydsy1708月赛】
给定一个长度为 \(n\) 的数组 \(p_i\),存在一个字符串 \(S\) 满足 \(S\) 的长度为 \(i\) 的前缀的循环节长度为 \(p_i\),请复原字典序最小的 \(S\)。
我们称 \(T\) 是 \(S\) 的循环节当且仅当 \(S\) 是 \(T\) 的无限复制串的前缀。
\(1\leq n\leq 10^5\)。
首先,\(\text{nxt}_i = i - p_i\)。
从前往后考虑,对于 \(\text{nxt}_i > 0\),那么显然 \(S_i = S_{\text{nxt}_i}\);反之,我们已知 \(S_i\) 将会与哪些位置进行匹配,我们要让 \(S_i\) 在这些位置全部失配,找出字典序最小且未在匹配位置出现的字符即可。
Fri
Z函数初探
Om Nom and Necklace
【CF526D】
给定一个长度为 \(n\) 的字符串 \(S\) 和正整数 \(k\),求 \(S\) 的每一个前缀能否被写成 \(ABAB\cdots BA\) 的形式,其中 \(A\) 有 \(k+1\) 个,\(B\) 有 \(k\) 个。
你说得对,但是Om Nom可爱捏
首先跑 KMP 求出的 \(\text{nxt}_i\) 数组可以求最小循环节。
根据 KMP 的相关性质,我们可以求出 \(len\) 为最小循环节长度,\(num\) 表示最小循环节个数,\(rem\) 表示除去最小循环节剩余的部分。
同时,我们要至少分出 \(k\) 组 \(AB\),记每一组由 \(sh\) 个最小循环节构成。
记 \(C\) 表示最短的循环节,则每一个前缀 \(P_i\) 要么形式为 \(CCCC\cdots CC\) 或 \(CCCC\cdots CCR\)。
而 \(AB\) 也需要成为循环节,那么 \(AB\) 肯定也是由若干个 \(C\) 组成,那么 \(A\) 包括若干个 \(C\) 和一个 \(C\) 的前缀,\(B\) 包括对应的后缀以及其余所有 \(C\)。
- 如果形式为 \(CCCC\cdots CCR\),即 \(rem\ne 0\)。
- 显然 \(A\) 不为空,因为 \(R\ne C\),所以 \(A\) 不对应 \(C\) 的完整前缀,所以 \(B\) 一定有 \(C\) 的一个后缀,则 \(B\) 不能为空,需要判断 \(B\) 不能为空。
- 那么,显然 \(A\) 中包含了 \(num - k\times sh = num \bmod k\) 个完整的 \(C\),则要求 \(sh > num\bmod k\)。
- 如果形式为 \(CCCC\cdots CC\),即 \(rem = 0\)。
- 如果 \(A,B\) 不为空,那么则将最后一个 \(C\) 视作 \(R\) 回到上一种情况。
- 如果 \(B\) 为空,此时就相当于视作可以 \(sh = num\bmod k\)。
- 如果 \(A\) 为空,此时依旧要求 \(sh > num \bmod k\)。