【border相关】【P3426】 [POI2005]SZA-Template
【border相关】【P3426】 [POI2005]SZA-Template
Description
给定一个字符串 \(S\),要求一个最短的字符串 \(T\),使得 \(S\) 可以由 \(T\) 不断在后面接上自身得到。在拼接的时候, \(T\) 的某个后缀如果与某个前缀相同,则相同的部分可以算作一个,不再重复出现。
Limitations
\(1 \leq |S| \leq 5 \times 10^5\)
Solution
介绍一个叫 \(border\) 树的东西,在 OI 中被称作 \(next\) 树。
记 \(S\) 的前缀 \(i\) 的最长 \(border\) 为 \(border_i\),考虑在 \(i\) 和 \(border_i\) 之间连一条边,最终会形成一棵以 \(0\) 为根的树。
证明上,考虑这棵树有 \(n + 1\) 个节点,而显然 \(border_i < i\),因此每个节点连向 \(border\) 的边都是互不重复的,共有 \(n\) 条边,由此可以证明这是一颗树。
这棵树有两个优美的性质:
节点 \(u\) 的祖先集合是 \(u\) 的所有 \(border\) 集合
节点 \(u\) 的后代集合是 \(u\) 能作为 \(border\) 的 \(S\) 的前缀子串集合
对于性质 \(1\),根据定义,\(u\) 的父节点是 \(u\) 的最长 \(border\),迭代证明即可。
性质 \(2\) 可以由性质 \(1\) 反推得到。
现在考虑本题。
一个显而易见的结论是 \(T\) 一定是 \(S\) 的 \(border\)。
因此我们考虑枚举 \(S\) 的所有 \(border\),我们发现对于长度为 \(i\) 的 \(border\),如果将他在 \(border\) 树上的后代拿下来排序以后相邻两数差值的最大值大于 \(i\),则这个 \(border\) 不能作为答案,因为对于插值最大的两个数,在拼接到左边的位置以后再加一个长度为 \(i\) 的 \(T\) 不能拼接到右侧的数,反之可以证明这个 \(border\) 是合法的。
我们考虑维护 \(border\) 的所有后代,从长到短枚举 \(border\) 时,相当于从 \(border\) 树的某个叶节点一直枚举到根,我们发现 \(border\) 变短时只会加入一些节点而不会删除,因此用一个 set 去维护这些后代,用 multiset 维护插值最大值即可。
时间复杂度 \(O(|S| \log |S|)\)
Code
写代码的时候发现一个有关 multiset 的有趣的事:erase某个值的时候,会将全部的该值删掉,如果想要只删掉一个,需要 s.erase(s.find(x))。
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
const int maxn = 500005;
int n, ans;
char MU[maxn];
int border[maxn];
std::set<int>s;
std::multiset<int>ms;
std::vector<int>son[maxn];
void KMP();
int ReadStr(char *p);
void dfs(const int u);
void update(const int x);
void KMP();
int main() {
freopen("1.in", "r", stdin);
n = ReadStr(MU + 1);
KMP();
update(n);
for (int i = border[n], j = n; i; j = i, i = border[i]) {
update(i);
for (auto u : son[i]) if (u != j) {
dfs(u);
}
if (*(--ms.end()) <= i) {
ans = i;
}
}
qw(ans, '\n', true);
return 0;
}
int ReadStr(char *p) {
auto beg = p;
do *p = IPT::GetChar(); while ((*p > 'z') || (*p < 'a'));
do *(++p) = IPT::GetChar(); while ((*p >= 'a') && (*p <= 'z'));
*p = 0;
return p - beg;
}
void KMP() {
for (int i = 2, j = 0; i <= n; ++i) {
while (j && (MU[i] != MU[j + 1])) j = border[j];
if (MU[i] == MU[j + 1]) ++j;
son[border[i] = j].push_back(i);
}
}
void dfs(const int u) {
update(u);
for (auto v : son[u]) {
dfs(v);
}
}
void update(const int x) {
auto u = s.insert(x).first, ftmp = u, btmp = u;
--ftmp; ++btmp;
if ((u != s.begin()) && (btmp != s.end())) {
ms.erase(ms.find(*btmp - *ftmp));
}
if (u != s.begin()) {
ms.insert(x - *ftmp);
}
if (btmp != s.end()) {
ms.insert(*btmp - x);
}
}
【border相关】【P3426】 [POI2005]SZA-Template的更多相关文章
- P3426 [POI2005]SZA-Template
P3426 [POI2005]SZA-Template 链接 分析: 首先T一定是S的一个前缀,也是一个后缀. 判断一个前缀s[1...i]是不是满足条件,那么求出s[1...i]在s中出现的所有位置 ...
- 2021.11.09 P3426 [POI2005]SZA-Template(KMP+DP)
2021.11.09 P3426 [POI2005]SZA-Template(KMP+DP) https://www.luogu.com.cn/problem/P3426 题意: 你打算在纸上印一串字 ...
- 用CSS border相关属性画三角形
效果 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2l3aV9jb2Rlcg==/font/5a6L5L2T/fontsize/400/fill/I0J ...
- Border性质习题与证明
KMP 第一次接触 \(border\) 都是先从 KMP 开始的吧. 思想在于先对于一个串自匹配以求出 fail 指针(也就是 border) 然后就可以在匹配其他串的时候非常自然的失配转移.在此顺 ...
- template package (godoc 翻译)
template 包 概述(Overview) template 包实现了数据驱动模板用于生成文本输出. 要生成HTML输出,请参阅html/template包,它具有与此包相同的接口,但会自动保护H ...
- Element-UI使用相关问题
1.如何修改el-dialog的样式? 要修改dialog的样式不能直接在<style scoped>中修改,这样修改后不会生效.做法是把scoped去掉,然后在dialog标签上自定义一 ...
- Django-mtv开发模式
从著名的MVC模式开始说起 所谓的MVC就是把Web应用分为模型(M)控制器(C)和视图(V)三层,他们之间以一种插件式的.松耦合的房还是 连接在一起,模型负责业务对象与数据库的映射(ORM),视图负 ...
- UWP Button添加圆角阴影(一)
原文:UWP Button添加圆角阴影(一) 众所周知,17763之前的UWP控件,大部分是没有圆角属性的:而阴影也只有17763中的ThemeShadow可以直接在xaml中使用,之前的版本只能用D ...
- Silverlight 之 浅析
一.silverlight定义及作用 silverlight用XAML来做前端界面,用.NET或者JS作为程序脚本支持,在浏览器内外运行的应用.可以认为和FLASH 和ADOBE AIR有很大的功能重 ...
随机推荐
- Gitlab安装、备份与恢复
背景:由于需要把gitlab从A服务器转移到B服务器,故在B服务器进行gitlab的安装和恢复备份 步骤: 一.在B服务器安装Gitlab 1. 获取安装包 wget https://mirrors. ...
- Salesforce学习之路(二)Profile
如上篇文章所述,针对User来讲,最重要的概念便是Profile和Role,因为Profile于Security息息相关,这是一个合格的产品中十分重要的一环. 何为Profile? 前文所讲--就是一 ...
- Vue.js 源码分析(十一) 基础篇 过滤器 filters属性详解
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化.过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持).过滤器应该被添加在 JavaScrip ...
- Destoon手机搜索点击提示 http 403 forbidden解决方法
以下是网上搜到的答案: 最近发现用destoon开发的手机版网站,在手机版百度搜素网站的时候,点击之后出现 http 403 forbidden的弹出窗.必须再次的刷新网页才可以打开网站.出现这个问题 ...
- [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ'
在Navicat Premium中执行Mysql的一条删除语句,虽然执行成功了,却提示已下错误: 受影响的行: 时间: .005s of ORDER BY clause is not in GROUP ...
- C#异步的世界【上】(转)
新进阶的程序员可能对async.await用得比较多,却对之前的异步了解甚少.本人就是此类,因此打算回顾学习下异步的进化史. 本文主要是回顾async异步模式之前的异步,下篇文章再来重点分析async ...
- 从时序异常检测(Time series anomaly detection algorithm)算法原理讨论到时序异常检测应用的思考
1. 主要观点总结 0x1:什么场景下应用时序算法有效 历史数据可以被用来预测未来数据,对于一些周期性或者趋势性较强的时间序列领域问题,时序分解和时序预测算法可以发挥较好的作用,例如: 四季与天气的关 ...
- 猫狗识别——PyTorch
猫狗识别 数据集下载: 网盘链接:https://pan.baidu.com/s/1SlNAPf3NbgPyf93XluM7Fg 提取密码:hpn4 1. 要导入的包 import os import ...
- thread stack size not set; configure via D:\Program Files\elasticsearch-5.0.0\config\jvm.options or ES_JAVA_OPTS
抄自:http://blog.csdn.net/leo063/article/details/52994786 thread stack size not set; configure via D:\ ...
- .Net MVC伪静态实现
伪静态的好处就不多说了 这里说一下Mvc具体实现的方法 第一步 打开根目录的Web.config 给webServer 节点下的modules 添加属性runAllManagedModulesFo ...