Files
troupe-standup/wizard-work/beam/manacher.py
T

50 lines
1.3 KiB
Python

"""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)