guest@cp-base:~/home/strings$
templates/manacher.cpp
compilable
$cat templates/manacher

Manacher's Algorithm

Find all palindromic substrings in O(n) time using linear expansion with symmetry reuse.

[Strings]|
Jul 9, 2026
|explanatory_notes.md|
#manacher#palindrome#string#linear
Log in to track progress, save custom versions, and organize into collections.Log In
$cat source_code/
cpp
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
#include <bits/stdc++.h>
using namespace std;

vector<int> manacher(const string &s) {
    string t = "#";
    for (char c : s) { t += c; t += '#'; }
    int n = t.size();
    vector<int> p(n);
    int l = 0, r = -1;
    for (int i = 0; i < n; i++) {
        int k = (i > r) ? 1 : min(p[l + r - i], r - i + 1);
        while (i - k >= 0 && i + k < n && t[i - k] == t[i + k])
            k++;
        p[i] = k--;
        if (i + k > r) { l = i - k; r = i + k; }
    }
    return p;
}
18 linesutf-8
$cat explanation_notes.md
notes_viewer --renderedmarkdown (math enabled)

Manacher's Algorithm

Finds all palindromic substrings in O(n)O(n) by exploiting the symmetry of already-discovered palindromes.

How It Works

  • Insert # between every character: aba#a#b#a#. Now every palindrome (odd and even) is odd-length in the transformed string

  • For each position ii, compute p[i]p[i] = largest radius where t[ik..i+k]t[i-k..i+k] is a palindrome

  • Maintain the rightmost palindrome boundary [l,r][l, r]:

  • - If iri \le r: reuse the mirror position's radius as starting point
    - Expand outward while characters match
    - Update [l,r][l, r] if current palindrome extends further right

    Converting Back

  • Original center: i/2i / 2

  • Palindrome length in original string: p[i]1p[i] - 1

  • Odd indices → odd-length palindromes, even indices → even-length
  • When to Use

  • Finding all palindromic substrings

  • Longest palindromic substring

  • Palindrome counting or decomposition
  • Complexity

  • Time — O(n)O(n) (right boundary rr never decreases)

  • Space — O(n)O(n)