Manacher算法

  1. 预处理:统一奇偶长度
    • 回文串有奇数长度(如”aba”)和偶数长度(如”abba”)之分,这会给统一处理带来麻烦。
    • Manacher算法通过在原始字符串的每个字符之间以及首尾插入一个原字符串中不存在的特殊字符(通常用#)来进行预处理。例如,"abba"会被处理成 "#a#b#b#a#"
    • 这样做的好处是:无论原字符串如何,新字符串的长度总是奇数,所有回文子串都变成了奇数长度,从而可以统一以每个字符为中心进行扩展检查。
  2. 利用回文对称性
    • 算法维护一个回文半径数组 P(也称为辅助数组),P[i]表示以新字符串中第 i个字符为中心的最长回文子串的半径(包含中心字符本身)。例如,对于字符串 "#a#b#a#",以中间的 b(位于索引4)为中心,其回文半径是4。
    • 关键在于,算法在从左至右遍历字符串时,会动态维护一个当前已知的最右回文边界 R 以及达到该边界的中心位置 C
    • 当遍历到位置 i时,如果 i在当前最右边界 R之内,则可以找到 i关于中心 C的对称点 j。根据回文的对称性,可以利用 P[j]的值来快速确定 P[i]的一个初始最小值,从而避免从1开始逐个字符扩展,大大减少了比较次数。这通常归纳为几种情况:
      • 如果 j的回文区域完全包含在 C的大回文区域内,那么 P[i]直接等于 P[j]
      • 如果 j的回文区域超出了 C的大回文区域,那么 P[i]至少为 R - i
      • 如果 j的回文区域恰好到达 C的大回文区域边界,则 P[i]的初始值设为 R - i,并需要继续向两侧扩展检查。
    • 如果 i超出了 R,则无法利用对称性,只能进行朴素的中心扩展。
    • 无论哪种情况,在获得初始值后,算法都会尝试继续向两侧扩展,以检查是否能得到更长的回文串,并相应地更新 RC