题解:P11276 第一首歌

闲话

本篇题解来自赛场第二切,比@dead_X 慢了整整 0.6s0.6s

Pro

给定 ss,求一个最短字符串 tt,使得 sstt 的最长 border。

Sol

前置知识:KMP,记号 a|a| 表示字符串 aa 的长度。

首先我们可以输出这个字符串,因为 sstt 的 border,tt 的前缀就一定是 ss

接下来考虑后缀怎么为 ss

KMP 中,有一个数组叫做 nxtnxtnxtinxt_i 表示 ss 的前 ii 个字符的 border。怎么求 nxtnxt 详见原题

因为 tt 的长度不会超过 2s2|s|,所以 ss 一定有一段前缀会和它的一段后缀重合。

ss 是一个类似 QwQ(其实就是的)的结构,那么 tt 一定会构造出一个形如 QwQwQ 的结构。

QQss 的最长 border 时,一定是最优的,因为 QQ 再长一定会不符合题意,再短一定不优。

所以求出 ssnxtnxt 数组,输出 ss 以及 ssnxts+1nxt_{|s|}+1sizes\text{size}_s 的所有字符。

时间复杂度 O(s)O(|s|)

Code

仅展示核心代码。

b=" "+b;
kmp(b);
for(int i=1;i<=n;i++) cout<<b[i];
for(int i=nxt[n/*n=|s|*/]+1;i<=n;i++) cout<<b[i];
}

后记

@dead_X 我**你*。

posted @ 2024-11-15 09:07  sLMxf  阅读(13)  评论(0)    收藏  举报  来源