manacher算法时间复杂度为o(n),中心扩展法最坏o(n²);中心扩展易越界因right边界判定错误,manacher中b[i] = min(b[2*pos-i], mxr-i)是因对称回文可能超出mxr,需从mxr重新比对,且坐标映射(i - b[i] + 1) / 2整除偏差会导致子串截取错误。

Manacher 算法能稳定做到 O(n),中心扩展法平均快但最坏仍是 O(n²);实际项目中若字符串长度常超 10⁴,别用中心扩展——它会在全相同字符(如 "aaaaa...")上退化成平方级耗时。
为什么中心扩展法的 expand 函数容易越界?
常见错误是把 right 判定写成 right ,但扩展时 <code>right 可能等于 s.size(),再访问 s[right] 就越界。正确逻辑是:先检查边界,再取值。
while (left >= 0 && right —— 顺序不能错,<code>&&短路保证不越界访问- 返回长度用
right - left - 1,不是right - left + 1;因为退出循环时left和right已各多走了一步 - 调用时传
const string& s,避免每次复制字符串(尤其长串下内存和时间双浪费)
manacher 预处理必须加哨兵字符吗?
必须。不加 '$' 和末尾 '<p>必须。不加 <code>'$' 和末尾 '\0',while (a[i + b[i]] == a[i - b[i]]) 在边界会越界读内存——C++ 不做自动边界防护。
while (a[i + b[i]] == a[i - b[i]]) 在边界会越界读内存——C++ 不做自动边界防护。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 标准预处理:开头加
'$',字符间插'#',结尾加'\0',例如"abba"→"$#a#b#b#a#\0" -
b[i](即p[i])存的是「半径」,包含中心,所以原串回文长度 =b[i] - 1 - 初始化
mxr = 0, pos = 0,不是-1或1;否则第一次i=0时mxr > i不成立,无法触发对称复用逻辑
Manacher 的 min(b[2*pos-i], mxr-i) 为什么不能直接赋 b[i] = b[2*pos-i]?
因为对称位置 j = 2*pos-i 的回文可能「撑破」当前已知右边界 mxr,此时只能安全复用到 mxr-i 这段长度,再多就得实测。
- 若
b[j] :说明 <code>j的回文完全落在(2*pos-mxr, mxr)内 →b[i] = b[j]安全 - 若
b[j] > mxr - i:说明j的回文左端超出了已知左边界 →b[i]至少为mxr - i,但右边必须从mxr开始重新比对 - 漏掉
mxr-i截断会导致算法在"abacabad"类串上算错b[i],进而漏掉最长回文
Manacher 真正难调试的点不在主循环,而在预处理字符串索引与原串坐标的映射——b[i] 最大值对应的位置,要反推回原串起始下标,(i - b[i] + 1) / 2 这个公式里整除方向稍错一位,截出来的子串就偏了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










