문제에서 원하는 것은 엄청 단순하다, 문자열 s가 주어질 때 s에서 가장 긴 팔린드롬 부분 문자열을 반환하는 문제이다.
Brute Force 로 푸는 방법이 있다. 이중 for 문을 돌면서 i번째 문자를 중심으로 하는 가장 긴 부분 문자열을 찾는 방법이다. 이 방법으로 풀면 100% 시간 초과가 발생한다.
다음 방법은 Brute Force에서 반복된 부분에 대해서 다이나믹 프로그래밍을 활용한다. 알고리즘의 이름은 Manacher 알고리즘으로 불린다.
짝수 길이 문자열에 Manacher 알고리즘을 사용하면 가장 긴 팔린드롬 부분문자열을 찾을 수 없다. 그래서 문자열 s가 주어질 때 주어진 문자사이 마다 '#'이나, '@'을 추가한다면 Manacher 알고리즘을 적용해서 정답을 찾을 수 있다.
class Solution:
def longestPalindrome(self, s: str) -> str:
def addSharp(string) -> str:
result = '#'
for ss in string:
result += ss + '#'
return result
def manacher(string) -> str:
sharped = addSharp(s)
a = [0] * len(sharped)
p = r = 0
for i in range(len(sharped)):
if i <= r:
a[i] = min(r - i, a[2 * p - i])
else:
a[i] = 0
while i - a[i] -1 >= 0 and i + a[i] + 1 < len(sharped) and sharped[i - a[i] - 1] == sharped[i + a[i] + 1]:
a[i] += 1
if r < i + a[i]:
# r은 반지름이 아니라 i 번째 문자를 중심으로 하는 가장 긴 팔린드롬의 가장 길이
r = i + a[i]
p = i
maxIndex = a.index(max(a))
answer = sharped[maxIndex-a[maxIndex]:maxIndex+a[maxIndex] + 1].replace('#', '')
return answer
return manacher(s)