"""Manacher's algorithm: longest palindromic substring in O(n).""" from __future__ import annotations def longest_palindrome(s: str) -> str: if s == "": return "" # Transform: insert sentinels so every palindrome has odd length. t = "^#" + "#".join(s) + "#$" n = len(t) p = [0] * n c = r = 0 for i in range(1, n - 1): mirror = 2 * c - i if i < r: p[i] = min(r - i, p[mirror]) # expand while t[i + p[i] + 1] == t[i - p[i] - 1]: p[i] += 1 if i + p[i] > r: c = i r = i + p[i] # find center with max radius center = 1 for i in range(1, n - 1): if p[i] > p[center]: center = i start = (center - p[center]) // 2 return s[start:start + p[center]] def all_palindromic_substrings(s: str) -> list[str]: """Return all distinct palindromic substrings (may be large).""" res = set() n = len(s) for i in range(n): # odd l = r = i while l >= 0 and r < n and s[l] == s[r]: res.add(s[l:r + 1]) l -= 1 r += 1 # even l, r = i, i + 1 while l >= 0 and r < n and s[l] == s[r]: res.add(s[l:r + 1]) l -= 1 r += 1 return sorted(res)