【题解】Solution Set - NOIP2024集训Day58 字符串

【题解】Solution Set - NOIP2024集训Day58 字符串

https://www.becoder.com.cn/contest/5658


「CF1466G」Song of the Sirens

考虑对于 \(s_i\),算钦定必须覆盖到 \(t_i\) 的匹配个数 \(f_i\),其对答案的贡献为 \(2^{k-i}f_i\)

注意到 \(s\) 每次长度都会 \(\times ~2\) 左右,其长度在 \(O(\log |w|)\) 的时候就会超过 \(|w|\),而在此之后 \(f_i\) 可能匹配到的字符串只会有 \(t_i\) 这一位不同。

对于后面这一部分,我们直接 \(O(w)\) 暴力枚举 \(w\) 的每一位作为 \(t_i\),来算 \(f_i\)

而前面这一部分,每一次 \(O(w)\) 维护 hash,同样 \(O(w)\)\(f_i\)。一共 \(O(\log |w|)\) 次。

所以总时间复杂度为 \(O(w\log w)\)

22min


「QOJ9372」Prefix of Suffixes

显然把 \(B_i\) 提出来,即有:

\[Ans=\sum_{i=1}^nB_i\sum_{j=i}^{i+z_i-1}A_j \]

现在的问题在于如何去维护后面这个 \(A\) 的区间和。

考虑从上一次的答案继承过来。(下面的 \(n\) 都是在加入 \(s_i\) 后的 \(n\)

显然,\(i=n\) 可以单独处理,而对于一个 \(z_i,i<n\) 其要增大的一个必要条件是 \(z_i=n-i\) 也即 \([i,n)\) 成为一个 border。也就是说对于 \(n-1\) 的每个 border 设其长度为 \(l\),如果 \(s_l=s_i\) 那么这个 \(z_i\) 可以累加 \(1\) 并成为新的 border。我们要算这些 border 的 \(B\) 的总和,然后和 \(A_i\) 相乘累加到答案。

bf

每次可以在 \(O(\log n)\) 的时间复杂度内,遍历每个本质不同的 border。具体的做法是:

对于一个字符串 \(s\)

设当前的 border 长度为 \(l\)。分讨:

  1. \(2l\le |s|\):直接暴力跳就行了;

  2. \(2l>|s|\)

    \(k=|s|-l\),则 \(s[1\dots k]\)\(s\) 的一个周期。

    由 Weak Periodicity Lemma 的推论可以知道:

    此时 \(s\) 的 border 集合中长度 \(\ge k+(|s|\bmod k)\) 的元素一定构成集合 \(\{pk+(|s|\bmod k)|p\in\mathbb N^{+}\}\)

    详细证明可以见 这篇题解

    对于这些这些 border 她们一般会有一些良好的性质。比如这道题里面每个 border 的后一位均相同。

    既然如此,我们把这些的 \(B\) 打包起来一起算。

    然后下一次直接跳到 \(k\),而 \(2k< |s|\)

综上,我们每次跳都能使位置减半,故能做 \(O(\log n)\) 的时间复杂度。

26min


膜拜高手的神秘线性做法:https://www.becoder.com.cn/submission/2664090

前面部分大体差不多,只是后面算 \(B\) 的总和(也即高手所说的 \(g\))的时候,高手也是从上一次继承过来的,而我是直接较暴力的 \(O(\log n)\) 来算的。


自己实现了一下,发现那些 \(B\) 并不太能打包起来算,还是得从上一位继承过来。

另外一份也是 \(O(n\log n)\) 但是从之前继承的题解:https://www.cnblogs.com/cjjsb/p/18427542#c-prefix-of-suffixes


题外话,来源似乎是:https://www.cnblogs.com/yyyyxh/p/KMP-Z.html


「CEOI2011」Matching

直接枚举每一个长度为 \(n\) 的子串。我们维护一个 \(\sum P^{c}i\)\(c\) 表示比 \(i\) 小的个数。然后去跟 \(\sum P^{i-1}a_i\) 比。

总感觉和 这道题 有点莫名相像。(实际上代码也是这道题改的。

7min

(上面写的有点模糊,具体可以见代码


「POI2011」Periodicity

首先答案的第一位一定是 \(0\)(否则反转所有位一定更优。

感觉上来说有点像反悔贪心。

18min(没什么思路。


https://www.luogu.com.cn/article/2jepwn0f

注意 Weak Periodicity Lemma 及其推论。具体可见这篇题解。

(基于此,我们还可以对于任意前缀在 \(O(\log n)\) 的时间复杂度内,找出其所有的 border(注意是找出不代表个数。

第四个情况的分讨是真的把我整破防了。


「POI2005」Sza-Template

首先一个必要条件是答案必须是原串 border。(对但是好像没什么用。

暴力一点,直接建出 sam,然后线段树合并求出每个等价类的的 endpos。

枚举每个等价类,比较 endpos 之间差的最大值和等价类中最长子串长度 \(len\)。(注意特判开始和结尾必须等于 \(len\)\(n-len+1\)

11min(个人感觉没什么问题,实现虽然板但是比较多。

https://www.luogu.com.cn/record/184023802

对的但是被卡空间了。


https://www.luogu.com.cn/article/hd3hmymb

好像很有道理,可以直接 dp。


「POI2006」OKR-Periods of Words

做过。(但是当时好像没弄懂。


其实就是求最长循环节,也即长度 - 最短 border

而一般的 kmp 求的是最长 border。

我们再跑一遍,每次在 \(nxt\ne0\) 的情况下尽可能的跳 \(nxt\),这样就是最短的 border 了。

posted @ 2024-10-22 08:24  CloudWings  阅读(14)  评论(0编辑  收藏  举报