20251117 - Manacher

news/2025/11/18 18:38:45/文章来源:https://www.cnblogs.com/myblog-Ruochen/p/19238895

前言

怎么又有 ABB 啊,连考三次,罚时吃饱了!


Manacher,俗称马拉车,是一个可以线性的求出一个串的最长回文子串

如何求解最长回文子串呢? 马拉车


方法零

首先枚举字符串的左端点和右端点,在判断区间是否是回文串。

时间复杂度\(O(n^3)\)

空间复杂度\(O(n)\)

bool check(int l,int r){for(int i = l,j = r;i < j;i++,j--){if(s[i] != s[j]) return 0;}return 1;
}
for(int d = 1;d <= n;d++){ // 这是认真的吗?for(int i = 1;i + d - 1 <= n;i++){int j = i + d - 1;if(check(i,j)){ans = max(ans,j - i + 1);}}
}

方法一

枚举中间位置,再看看往两边扩充最大能到多少。

for(int i = 1;i <= n;i++){int l,r;l = r = i;while(l >= 1 && r <= n && s[l] == s[r]) l--,r++;ans = max(ans,r - l + 1);
}

方法二

通过打表严禁证明,可以发现,方法一是具有单调性的(长度),所以,就可以二分来搞。

还要用哈希来搞!

方法四:Manacher

方法三慢在扩充的过程,Manacher 就像 KMP 一样,根据已知的条件来得到最终答案。

如果回文的中心点不在上一个回文区间,那么就没有回文串与之匹配。

否则和对称的另一端和边界求一个 \(\min\)。(抄过来)

再暴力扩充即可!

void init(){s = tmp + 1;for(auto v : s){t += '$';t += v;}t = '_' + t + '$';n_ = t.size() - 1;d.resize(n_ + 2);
}
for(int mid = 1,l = 1,r = -1;mid <= n_;mid++){int len;if(mid > r){len = 1;}else{len = min(d[l+r-mid],r-mid+1);}while(mid - len >= 1 && mid + len <= n_ && t[mid-len] == t[mid+len]){len++;}d[mid] = len;if(mid + len - 1 > r){r = mid + len - 1;l = mid - len + 1;}}

例题: 拉拉队排练

首先看看 \(K\) 的范围:\(10^{12}\),如果跟 \(K\) 有关的,一定要是 \(\le log_k\)

回文子串,马拉车!

在马拉车时记录,在快速幂一下就好了!

#include <bits/stdc++.h>using namespace std;
#define ll long long
const int N = 2e6 + 7;
const int P = 19930726;
const int inf = (1 << 30);
template<class T> void read(T &x){x = 0;int f = 1;char ch = getchar();while(!(ch >= '0' && ch <= '9')){if(ch == '-') f = -f;ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}x *= f;
}
int n,n_,cnt[N];
ll k,ans = 1;
char tmp[N];
string s,t;
vector<int>d;
void init(){s = tmp + 1;for(auto v : s){t += '$';t += v;}t = '_' + t + '$';n_ = t.size() - 1;d.resize(n_ + 2);
}
int mcp(int x){return (int)ceil(x / 2.0) * 2 - 1;
}
ll ksm(ll a,ll b,ll mod){a %= mod;ll res = 1;while(b){if(b & 1){res *= a;res %= mod;}a *= a;a %= mod;b >>= 1;}return res;
}
int main(){read(n),read(k);scanf("%s",tmp+1);init();for(int mid = 1,l = 1,r = -1;mid <= n_;mid++){// 暴力扩充时会记录答案了!if(mid & 1) continue;int len;if(mid > r){len = 1;}else{len = min(d[l+r-mid],r-mid+1);}while(mid - len >= 1 && mid + len <= n_ && t[mid-len] == t[mid+len]){// cnt[mcp(len)]++;len++;}d[mid] = len;if(mid + len - 1 > r){r = mid + len - 1;l = mid - len + 1;}if(mcp(len) % 2) cnt[mcp(len)]++;}ll sum = 0;for(int i = n;i >= 1;i--){if(!(i & 1)) continue;sum += cnt[i];if(sum <= k){ans = (ans * ksm(i,sum,P)) % P;k -= sum;}else{ans = (ans * ksm(i,k,P)) % P;k -= sum;break;}}// for(int i = 1;i <= n;i++)// printf("%d %d\n",i,cnt[i]);if(k > 0) ans = -1;printf("%lld\n",ans);return 0;
}

后记

马拉车非常实用,一定要搞懂他!

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

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

相关文章

Prufer序列和Cayley定理

OI Wiki讲的还挺好的。 标号无根树 其实就是把一棵无根树标一下号,让每一个节点是唯一的。 双射 通俗来讲就是一个 \(A\) 可以对应到一个唯一确定的 \(B\),反之也是如此。 Prufer序列 构造 Prufer 序列的构建方法如下…

完整教程:PB级数据洪流下的抉择:从大数据架构师视角,深度解析时序数据库选型与性能优化(聚焦Apache IoTDB)

完整教程:PB级数据洪流下的抉择:从大数据架构师视角,深度解析时序数据库选型与性能优化(聚焦Apache IoTDB)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; dis…

软件工程学习日志2025.11.18

嗨,各位小伙伴,今天开始我想开一个新坑,用几天时间,聊聊如何为一个非常特殊的行业——医疗器械——设计一套进销存管理系统。这可不是普通的商品管理,它关乎人的健康与安全,所以咱们设计的系统,也得有点“医者仁…

11.14 事务的四大特性 并发事务问题

原子性 一致性 隔离性 持久性 脏读:一个事务读到另一个事务的未提交数据 不可重复读:一个事务读取同一条记录,数据不同 幻读:一个事务在读是未发现的数据却在插入时出现

SQL逻辑查询语句执行顺序

details summary::before { content: "▶"; position: absolute; left: 8px; transition: all 0.3s ease } details[open] summary::before { transform: rotate(90deg) } summary { list-style: none; curs…

解码死锁的产生与解决

死锁 死锁是多线程 / 多进程并发编程中常见的严重问题,指两个或多个线程 / 进程因互相争抢资源而陷入无限等待状态,若无外力干预将永久无法继续执行。其本质是资源分配与调度不当导致的 “资源僵局”,典型现实类比是…

uniapp的rich-text在渲染长数字与长字母时不换行

在rich-text的容器上新增 容器 容器 容器 不是rich-text组件本身word-break: break-all; word-wrap: break-word; 出现此问题是因为浏览器将其视为了一个单词所以未进行换行

头部厂商易路AI HR实战解析:从人海战术到智能闭环的合规跃迁

在连锁零售与餐饮行业,食品安全是企业的生命线,而员工健康证管理则是保障这条生命线的第一道防线。对于拥有数千家门店、数万名员工的行业巨头而言,健康证管理绝非一项简单的事务性工作,它关乎企业合规的基石、品牌…

【微信小程序 + 登录流程】微信小程序授权登录完整流程,一篇搞定!(含代码实现) - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

linux auto

您提到的“Linux auto”可能是指“Linux 自动化”或“Linux 自动化工具”,我将为您介绍一些常见的 Linux 自动化工具和命令,帮助您实现自动化任务。一、Linux 自动化工具 1. Ansible功能:基于 YAML 的自动化工具,支…

记录相关的操作

details summary::before { content: "▶"; position: absolute; left: 8px; transition: all 0.3s ease } details[open] summary::before { transform: rotate(90deg) } summary { list-style: none; curs…

P9846 [ICPC 2021 Nanjing R] Paimons Tree

派蒙题。 首先发现填完权值后的直接必定是原树直径中的某一条,但是无法确定是其中哪一条,所以这个发现是没用的/tx。 发现按照题目的染色方法,每个时刻染色的边必然为一条路径。 观察到 \(n\) 的范围很小,首先考虑…

linux audio

在 Linux 系统中,音频相关操作可以通过多种方式实现,包括使用内核音频驱动、 ALSA(Advanced Linux Sound Architecture)或 JACK 音频服务器等。以下是一些常见的 Linux 音频操作命令和脚本示例,适用于大多数 Linu…

不同方向的箭头符号

1. 基础方向箭头 ▶ 右箭头 (U+25B6) ◀ 左箭头 (U+25C0) ▼ 下箭头 (U+25BC) ▲ 上箭头 (U+25B2)2. 实心箭头 🔺 实心上三角 (U+1F53A) 🔻 实心下三角 (U+1F53B) ⏩ 快进右箭头 (U+23E9) ⏪ 快退左箭头 (U+23EA)3…

11.13 表子查询 内连接补充 事务

SELECT xx.*FROM(SELECT。。。。。; 内连接出来的是笛卡尔积,必须用条件消除 事务就是捆绑的操作集合 事务操作 SELECT @@autocommit ==1,自动提交 SET @@zutocommit=0; 手动提交: commint; 执行失败要回滚事务 ro…

Elasticsearch 7.17 集群添加账号密码

Elasticsearch 7.17 集群添加账号密码1. 环境信息 1.1 主机列表IP 主机名 操作系统 JAVA_HOME10.0.0.22 SY-AFP-ES01 Red Hat Enterprise Linux release 8.6 (Ootpa) /opt/app/middles/jdk1.8.0_47110.0.0.23 SY-AFP-E…

实用指南:【XR硬件系列】影目GO3智能眼镜发布:AI翻译+轻薄设计,重塑人机交互体验

实用指南:【XR硬件系列】影目GO3智能眼镜发布:AI翻译+轻薄设计,重塑人机交互体验pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; fo…

深入解析:推荐给硬件工程师的技术书籍

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

全球可观测厂商怎么选?2025年可观测性平台深度分析

在Gartner发布的《2025可观测性平台关键能力报告》中,评估维度涵盖数据摄取与存储、交互式探索、成本控制、LLM可观测性等核心能力,为全球企业选型提供了权威参考 根据Gartner报告描述的这几个核心能力,我们做了一个…

完整教程:PRCV 2025:文本何以成为 AGI 的必经之路?

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …