串串全家桶

news/2025/2/13 21:04:55/文章来源:https://www.cnblogs.com/stawalr/p/18714397

Manacher

用途:

该算法可在 \(O(n)\) 的时间复杂度下求出以每一个点(和缝,即回文串长为偶数的情况)为中心的最长回文串长度。

做法:

前置:定义朴素算法为,对于每一个点为中心的情况,暴力枚举是否可以扩展两边,直到不能扩展,此时得到结果。
代码如下,其中 \(a\) 是字符数组, \(x\) 是我们计算的中心,而 \(ans_x\) 则是答案。

while(a[x-ans[x]-1]==a[x+ans[x]+1])++ans[x];
  1. 预处理:在原串的 \(n+1\) 个缝里插入任意不在原串中的字符,在首和尾再插入两种之前不同的字符
    举个例子,若原串是 abcdefg ,一种合法的预处理方式是 @#a#b#c#d#e#f#g#$ 。插入的三种字符互不相同。
    在这个例子中,插入 # 的原因是显然的,如果我们有 a#a ,我们就可以计算出原串中长度为 \(2\) 的回文串。
    插入 @ $ 的原因是将他们作为哨兵,他们不可能被包含在回文串中,所以扫到它们的时候我们可以不用特判而知道停止扫描。
  2. 处理 \(ans\) :假设我们在处理位置 \(i\) 前已经处理出了 \(ans_{1\sim i-1}\) ,我们维护当前最右的被之前的回文串包住的位置为 \(r\),则若 \(r<=i\),则我们直接对该位置做朴素算法;否则,我们可以给 \(ans_i\) 赋上一个初值,从而减少重复的枚举。
    若使得 \(r\) 最大的位置为 \(p\) ,则我们可以把 \(i\) 关于 \(p\) 对称的位置的 \(ans\) 赋给 \(i\),给出一张图来解释原因。

    但是,我们不难发现,这个好像只在 \(p\) 的回文串包含 \(i'\) 时才成立,如果是下图的情况,我们简单分析可以发现初值应为 \(r-i\) ,因为我们并不能保证两绿色段拼上后合法。

由此我们做完了。

复杂度分析

$case_1: i\ge r $ 此时,朴素算法拓展次数等于 \(r\) 的增量。
$case_2: i<r \wedge $ 回文串范围被 \(r\) 覆盖 此时 \(ans_i\) 初值等于末值,朴素算法执行 \(1\) 次。
$case_3: i<r \wedge $ 回文串范围未被 \(r\) 覆盖 此时 \(i+ans_i\) 初始 \(=r\) ,朴素算法拓展次数等于 \(r\) 的增量。
由于 \(r\) 最多被增加 \(n\) 次,所以该算法复杂度为 \(O(n)\)

code
int r,nid;
void calc(int x)
{while(a[x-ans[x]-1]==a[x+ans[x]+1])++ans[x];if(r<x+ans[x]){r=x+ans[x];nid=x;}
}
for(int i=1;i<=tp;i++)
{if(i<=r){ans[i]=min(ans[nid*2-i],r-i);}calc(i);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/883396.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#字符串拼接的6种方式及其性能分析对比

前言 在C#编程中字符串拼接是一种常见且基础的操作,广泛应用于各种场景,如动态生成SQL查询、构建日志信息、格式化用户显示内容等。然而,不同的字符串拼接方式在性能和内存使用上可能存在显著差异。今天咱们一起来看看在C#中字符串拼接的常见6种方式及其使用BenchmarkDotNet…

寒假集训专题五:搜索

ESAY1:自然数的拆分 P2404 自然数的拆分问题 题目描述 任何一个大于 \(1\) 的自然数 \(n\),总可以拆分成若干个小于 \(n\) 的自然数之和。现在给你一个自然数 \(n\),要求你求出 \(n\) 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,…

多模态 AI 怎么玩?这里有 18 个脑洞

在 RTE 开发者社区,我们会和大家一起探索全球最前沿的 Real-Time AI 技术,和最有想法的新兴场景。Google 近期举办了一场名为「MultiModal Hackathon」的限时编程活动,聚焦于 多模态与 Gemini 2.0 的最新能力。活动汇聚了 200 多位开发者,共同探索多模态 AI、实时 AI、生成…

Svelte 最新中文文档翻译(7)—— snippet 与 @render

前言 Svelte,一个非常“有趣”、用起来“很爽”的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构…

基环树 DP:学习笔记

总述 定义 基环树,是一个 \(N\) 个点和 \(N\) 条边的连通图,特征是图中有且仅有一个环。特别的,如果不连通且每个连通块的点数和边数都相等,那么这就是一个基环树森林。 基环树 DP,顾名思义,就是在一个基环树上 DP,或是 DP 的结构类似基环树。相对于正常的树型 DP,一般…

数字孪生如何让GIS场景视效瞬间高大上?带你了解鲸孪生中的GIS系统

GIS与数字孪生的结合非常紧密,而山海鲸可视化作为一个数字孪生平台,也将GIS系统整合在了鲸孪生功能之中。 GIS中包含了大量的数据,例如遥感数据、地形数据、倾斜摄影数据等,能够为数字孪生系统提供非常好的补充。同时,传统的GIS系统整体视觉效果相对较差,与其他模型和数据…

2 分支 多个思路

利用分支,你就可以在同一个代码基础上同时处理多个完全没有关联、相互独立的工作。考虑以下场景。 假设你正在改一个 Bug-A,此时已经产生了大量的代码修改,并且离修复完成还有很长一段时间(起码得明天)。此时,有一个着急但简单的 Bug-B 需要你立即完成,并在一个小时内同…

记录一种DAG计数方法与一个配套技巧

记录一种DAG计数方法与一个配套技巧 定义 \(f_S\) 表示集合 \(S\) 中的点构成的合法 DAG 子图的方案数。假设找到 DAG 中一个入度为 \(0\) 的节点 \(x\),那么很明显 \(f_S=\sum_{x}f_{S\setminus \{x\}}\),这明显要算重因为 \(S\setminus \{x\}\) 中也有入度为 \(0\) 的点。 …

野鸡题手写题解整合

浴谷正在蒸蒸日上,专栏区怕是马上要倒闭了。 CF2026F 题 题。题外话:这场有点水平,E 题让我重拾了最大权闭合子图的记忆。 首先考虑没有这个可持久化(只有 \(2,3,4\) 操作)怎么做。\(0/1\) 背包问题,动态维护当前的 dp 数组 \(f_i\) 表示总体积 \(\sum p\) 不超过 \(i\) …

鸿蒙开发:了解@Builder装饰器

@Builder装饰是鸿蒙UI开发中,非常重要的一个装饰器,在实际的开发中,合理且正确的使用,能够让我们的代码更加的简洁前言本文代码案例基于Api13,温馨提示:内容相对来说比较简单,如果您已掌握,略过即可。如果说一个页面中组件有很多,我们都统一写到build函数中,显而易见…

P1020 [NOIP 1999 提高组] 导弹拦截(dilworth)

这道题真的做的我鬼火冒,尤其是这个第二问要用到dilworth但是我看讲解完全不知道他们在讲什么,我看了好久才理解,一个数组至少可以由几个不增子序列覆盖就等于严格单调递增的最长子序列的长度,如果是至少可以由几个严格递减子序列覆盖就等于最长单调不减子序列的长度,然后…

Linux系统介绍

1. Linux介绍 Linux和windows一样也是一个操作系统,但是与windows不同的是,Linux是一套开放源码的代码程序、并且可以自由传播的类unix操作系统软件。 Linux系统主要被应用于服务端、嵌入式开发和个人PC桌面3大领域,一般的WEB项目都是部署在Linux操作系统上。 Linux是一个基…