【border树】【P2375】动物园
Description
给定一个字符串 \(S\),对每个前缀求长度不超过该前缀一半的公共前后缀个数。
共有 \(T\) 组数据,每组数据的输出是 \(O(1)\) 的。
Limitations
\(1 \leq |S| \leq 10^6,~1 \leq T \leq 5\)
Solution
好水的NOI题
建出 \(border\) 树,对于树上每个节点,它的所有 \(border\) 与它的所有祖先一一对应。这是因为每个节点的父亲是它的最长 \(border\),数学归纳可以证明这个结论。
考虑对于这棵 \(border\) 树上任何一个节点到根的路径上节点的编号一定是单调减小的,这是因为每个结点的最长 \(border\) 显然小于自身。
因此,对于一个点 \(u\),如果 \(v\) 是一个合法的 \(border\),那么 \(v\) 的祖先一定是合法的 \(border\)。所以合法的 \(border\) 一定是一条以根为一个端点的链。
综合上面两条可以得出,如果 \(u\) 的合法 \(border\) 对应链的另一个端点为 \(v\),那么 \(u\) 的孩子的合法 \(border\) 的对应端点一定在 \(v\) 到 \(u\) 的路径上,因此这个端点位置是单调变深的。
所以只需要在 dfs 的时候维护根节点到该节点的链,并维护当前节点的答案位置即可。由于答案位置只会变大,因此答案位置的寻找是均摊 \(O(1)\) 的,暴力往下循环即可。
总时间复杂度 \(O(T |S|)\)。
Code
#include <cstdio>
#include <cstring>
#include <vector>
const int maxn = 1000006;
const int MOD = 1000000007;
int T;
int n, top;
ll ans;
char MU[maxn];
int border[maxn], pos[maxn], stack[maxn];
std::vector<int>son[maxn];
void KMP();
void clear();
int ReadStr(char *p);
void dfs(const int u);
int main() {
freopen("1.in", "r", stdin);
qr(T);
while (T--) {
clear();
n = ReadStr(MU + 1);
KMP();
for (int i = 1; i <= n; ++i) {
son[border[i]].push_back(i);
}
dfs(0);
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;
border[i] = j;
}
}
void clear() {
ans = 1; top = -1;
for (auto &u : son) {
u.clear();
}
memset(pos, 0, sizeof pos);
}
void dfs(const int u) {
stack[++top] = u;
for (auto v : son[u]) {
int dv = v >> 1;
int &_ans = pos[v];
_ans = pos[u];
while ((_ans < top) && (stack[_ans + 1] <= dv)) ++_ans;
dfs(v);
}
if (pos[u]) {
(ans += pos[u] * ans) %= MOD;
}
--top;
}
【border树】【P2375】动物园的更多相关文章
- 洛谷P2375 动物园
我要死了.这是我做过的最恶心的题之一. 天下第一的大毒瘤.有gay毒. 我不如熊猫好多年... 题意:给定字符串,求g[i],表示:[0, i]中满足该子串既是前缀又是后缀还不重叠的子串数. 解:题面 ...
- 洛谷 P2375 动物园
题目详情 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法 ...
- P2375 动物园
入口 题目的大意就是输出以任意一个字符结尾,既是前缀,又是后缀,且长度不超过总长度的一半的方案书的乘积. 考虑使用kmp 在处理失配数组的同时,处理出来以每个字符结尾的时的,能有多少个前缀和后缀相同的 ...
- Border Theory
持续更新中!!!更个屁,无线停更! 前言: KMP 学傻了,看 skyh 说啥 border 树,跑来学 border 理论 洛谷云剪切板:https://www.luogu.com.cn/paste ...
- 【border相关】【P3426】 [POI2005]SZA-Template
[border相关][P3426] [POI2005]SZA-Template Description 给定一个字符串 \(S\),要求一个最短的字符串 \(T\),使得 \(S\) 可以由 \(T\ ...
- 51nod1600 Simple KMP
题目描述 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i) 显然对于一个字符串,如果我们将每个0<=i<=|S|看 ...
- 模板库 ~ Template library
TOC 建议使用 Ctrl+F 搜索 . 目录 小工具 / C++ Tricks NOI Linux 1.0 快速读入 / 快速输出 简易小工具 无序映射器 简易调试器 文件 IO 位运算 Smart ...
- 洛谷 P2375 [NOI2014]动物园 解题报告
P2375 [NOI2014]动物园 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定 ...
- VIJOS P1081 野生动物园 SBT、划分树模板
[描述] cjBBteam拥有一个很大的野生动物园.这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子.这些狮子从北到南编号为1,2,3,…,N.每头狮子都有 ...
随机推荐
- 查看索引在哪些ES集群节点上的命令
用途:迁移数据到其他节点上的时候需要用这个 GET /_cat/shards GET /_cat/shards?h=n
- WPF 精修篇 旋转 RotateTransForm
原文:WPF 精修篇 旋转 RotateTransForm 旋转 RotateTransform Angle 角度 CenterY ,CenterX 中心点位置 和缩小一样 左侧 和右侧 做了对比 ...
- .net core使用jwt自动续期
小弟不C才,最近看了下网上的jwt方案,于是自己写了一个简单的jwt方案和大家分享下,希望大家给点意见! 假如有一个读书网站,可以不用登陆就访问,当需要自己写文章的时候就必须登录,并且登录之后如果一段 ...
- 使用linq对ado.net查询出来dataset集合转换成对象(查询出来的数据结构为一对多)
public async Task<IEnumerable<QuestionAllInfo>> GetAllQuestionByTypeIdAsync(int id) { st ...
- Vuex实现状态管理
Vuex使用总结 1 Vuex简介 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,Vuex抽取了各个组件的共享部分,以全局单例模式进行状态的管理.在原生vue中各个组件之间传值使用的 ...
- 使用GitHub/码云/Git个性化设置
参考链接:https://www.liaoxuefeng.com/wiki/896043488029600/900937935629664 这似乎很可笑,我还从来没有想过为一个网站的使用方法写一篇来记 ...
- 2-Rocketmq产品架构(参考阿里云)
参考链接:https://help.aliyun.com/document_detail/112008.htm
- 1-Kong文章记录
参考: https://www.cnblogs.com/duanxz/p/9770645.html 系列博客可参考: 开源API网关系统(Kong教程)入门到精通 https://www.cnblog ...
- 一文搞定十大经典排序算法(Java实现)
本文总结十大经典排序算法及变形,并提供Java实现. 参考文章: 十大经典排序算法总结(Java语言实现) 快速排序算法—左右指针法,挖坑法,前后指针法,递归和非递归 快速排序及优化(三路划分等) 一 ...
- 消息队列mq总结
一.消息队列概述消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有ActiveMQ,RabbitM ...