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\)


拆一下绝对值,得:

\[\begin{cases} X_i - X_j \leq E_i - E_j \implies E_j - X_j\leq E_i - X_i \\ X_j - X_i \leq E_i - E_j \implies E_j + X_j\leq E_i + X_i \\ \end{cases} \]

设每个人为点 \(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\)


问题很像修车,首先改掉每一道菜的容量。

然后发现边数巨大,需要动态加点,加边。

每增广一个厨师做一道菜后,再为这个厨师开一个新点继续跑最小费用最大流。

二分图再探

二分图 OI-wiki

二分图最大匹配 OI-Wiki

搭配飞行员

\(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\)


根据定义,即求最长反链。

相关表达式

对于二分图:

  1. 最大匹配 = 最小点覆盖
  2. 最大独立集 = \(n-\)最小点覆盖。

对于 DAG:

  1. 最小路径覆盖 = \(n-\)对应二分图的最大匹配。
  2. 最长反链 = 最小链覆盖 = \(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\) 的最小点覆盖。

证明:

  1. \(S\) 的大小等于最大匹配的大小。
    • 在左侧选择的一定是匹配点,左侧的某个匹配点未被选中仅当匹配的右部点被选中,每条匹配上恰好会选中一个点,右侧的非匹配点不会被 dfs,否则与最大匹配矛盾。
  2. \(S\) 覆盖所有边。
    • 考虑将边分成【左/右】部点【是/否】被 dfs 分成 \(4\) 类,若一条边没有被覆盖,仅当左端点被 dfs 到而右端点没有,而该情况不可能存在,矛盾。

\(S\) 的补集为一最大独立集,记为 \(I\),记拆点后两端均在 \(H\) 中的点为 \(T\),则 \(T\) 为最长反链。

证明:

  1. \(T\) 为一反链。
    • 如果其中存在一对点 \(x\)\(x'\)(一个点拆出来的)使得其不构成反链,仅当 \(x\)\(x'\) 有边,这与 dfs 过程矛盾。
  2. \(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\),满足:

  1. 所有顶点都至少被 \(k\) 条边覆盖。
  2. \(|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\) 的点的点集,则有:

\[\text{Mincut} = \underset{S\subseteq V}{\min}\{ (\underset{i\in S}{\sum} p_i) + (\underset{j\notin S}{\sum} s_j) + (\underset{i\notin S, j\in S}{\sum} c[i< j]) \} \]

如果选择对一个点同时割 \(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\) 到所有叶子节点不连通的最小代价,有:

\[f_i= \begin{cases} \min(w_i, \underset{j\in to_i}{\sum} f_j) & (i \text{ is not a leaf node})\\ w_i & (i \text{ is a leaf node})\\ \end{cases} \]

考虑树上 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,+)\) 则有:

\[\begin{bmatrix} g_i & w_i \\ 0 & 0 \\ \end{bmatrix} \times \begin{bmatrix} f_{h_i} \\ 0\\ \end{bmatrix} = \begin{bmatrix} f_{i} \\ 0\\ \end{bmatrix} \]

树剖维护即可。

Thur

KMP 相关

OI-Wiki

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函数初探

算法学习笔记

OI-wiki

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\)
posted @ 2024-04-06 15:37  ydzr00000  阅读(27)  评论(0编辑  收藏  举报