当前位置: 首页 > news >正文

Manacher算法实现

Manacher

Manacher 是一种 \(O(n)\) 的回文串查找方式.

朴素算法

长度为 \(n\) 的字符串最多有 \(n^2\) 个回文子串. 朴素算法枚举回文串的中心。朴素算法复杂度为 \(O(n^2)\) .

int find(string s){for (int i=0;i<s.size();i++){d1[i]=1;while(0<=i-d1[i] && i+d1[i]<s.size() && s[i-d1[i]]==s[i+d1[i]]){d1[i]++;}d2[i]=0;while(0<=i-d2[i]-1 && i+d2[i]<s.size() && s[i-d2[i]-1]==s[i+d2[i]]){d2[i]++;}}
}

其中 \(d1_i\) 表示以 \(i\) 为中心的奇回文串的数量, \(d2_i\) 表示以 \(i-1,i\) 为中心的偶回文串的数量。

Manacher算法

Manacher算法的核心在于记录一个最靠右的已知回文串,再枚举回文串右侧的中心时,可以直接继承回文串左侧的中心的数据。

图1:

\(1,\overbrace{2,\underbrace{3,4,5,6,7,8,9}_{\text{回文串,大小为7}},10,\underbrace{11,12,13,14,15,16,17}_{\text{继承前文的回文串,大小最大为7}},18}^{\text{回文串}},19,20\)

因为右侧回文串在大回文串内,所以与左侧对称,无法再延伸。

图2:

\(1,\overbrace{\underbrace{2,3,4,5,6,7,8,9}_{\text{回文串,大小为8}},10,\underbrace{11,12,13,14,15,16,17,18}_{\text{继承前文的回文串,大小最小为8}}}^{\text{回文串}},19,20\)

虽然右侧回文串在大回文串下,但是右端点可以延伸到大回文串之外,可能 \(S_2 \not = S_{19}\) ,所以可以再延伸。

实现细节

为了快速计算,我们维护已找到的最靠右的子回文串的 边界 \((l,r)\)。初始时,我们设 $l=1 $ 和 \(r=-1\)

现在假设我们要对下一个中心 \(i\) 计算 \(d_i\) ,而之前所有 \(d_{i-1}\) 中的值已计算完毕。我们将通过下列方式计算:

  • 如果 \(i\) 位于当前子回文串之外,即 \(i>r\),那么我们调用朴素算法。然后更新最右侧区间 \((l,r)\)

  • 对于 \(i \le r\) 的情况。首先在子回文串 \((l, r)\) 中反转位置 \(i\),即我们得到 \(j=l+(r-i)\) 。我们从已计算过的 \(d_j\) 的值中获取回文串大小。因为位置 \(j\) 同位置 \(i\) 对称,我们可以置 \(d_i=d_j\)

  • 然而对于图二的情况:当「内部」的回文串到达「外部」回文串的边界时,即 \(j-d_j+1 \le l\) 。因为在「外部」回文串范围以外的对称性没有保证,因此直接置 \(d_i=d_j\) 将是不正确的。为了正确处理这种情况,我们应该置 \(d_i=r-i\)。之后我们将运行朴素算法以尝试尽可能增加 \(d_i\) 的值。最后更新最右侧区间 \((l,r)\)

Manacher复杂度

考虑到每次执行朴素算法都会更新右端点 \(r\) ,所以实际算法复杂度为 \(O(n)\)

代码:

vector<int> d1(n);
int l=0,r=-1;
for(int i=0;i<n;i++){if(i>r) k=1;else k=min(d1[l+r-i],r-i+1);while(0<=i-k && i+k<n && s[i-k]==s[i+k]){k++;}d1[i]=k--;if(i+k>r){l=i-k;r=i+k;}
}
http://www.sczhlp.com/news/13823/

相关文章:

  • 题解:P11323 【MX-S7-T1】「SMOI-R2」Happy Card
  • day29大模型程序开发day04-多智能体编排实操(张飞诸葛亮转移智能体)
  • Luogu P13685 【MX-X16-T3】「DLESS-3」XOR and Impossible Problem 题解 [ 黄 ] [ Ad-hoc ] [ 值域分治 ]
  • 在K8S中,镜像下载策略有哪些?
  • 一道题
  • 八代凯美瑞中控usb连接carplay盒子音响有电流滋滋声的解决方案
  • 读书笔记: 数据仓库同步的陷阱与Oracle读一致性的奥秘
  • SDFZ contest 444 题解
  • 设计表 Design table _2 获取单元格内容
  • 最小二乘法计算触摸事件速度
  • Font Awesome 一个基于CSS和LESS的免费图标库工具包 【下载与使用教程】
  • 铝5052、铝6061、铝7075、铝2A12的主要区别表格:
  • 揭秘ChatGPT共享功能重大隐私漏洞的发现与报告过程
  • 红日靶场01
  • ABC 419 E(滑窗同余 + dp)
  • 与配置相关的设计表 Design table
  • 在 Ubuntu 上安装 Jenkins
  • 2025高效招聘体系搭建:Moka智能化系统落地方法论
  • 使用Python 与 Seq2Seq Transformer 的可变长度验证码识别
  • OpenAI 发布了 GPT-5,有哪些新特性值得关注?国内怎么使用GPT5?
  • loguru 用法
  • 8.17
  • 不知道干什么,谁能陪我聊天
  • 【前端开发】iconfont 阿里巴巴免费矢量图标库超级实用!
  • 采用DoraCloud免费版,部署20用户云桌面
  • 深度学习(修改onnx文件batchsize)
  • 虚树(Virtual Tree)学习笔记
  • ABC419题解
  • 牛 CDR3 单抗 “茎 - 旋钮” 结构的核心特性及学科启示
  • 题解:P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪