codingtest

가장 긴 팰린드롬

2025-10-06
2분 분량
JAVA프로그래머스

문제 링크

문제 풀이 시간 :

문제 요약

  • 문자열 s(길이 2,500 이하, 소문자만) 이 주어짐
  • 앞뒤가 같은 부분 문자열(팰린드롬) 중 가장 길이가 긴 것의 길이를 구해야 함
  • 즉, s의 부분문자열 중에서 좌우 대칭이 되는 가장 긴 구간의 길이를 찾는 문제

문제 풀이

이 문제는 처음보고 푼 방식이 순차탐색이었다.

초기 코드

java
class Solution
{
    public int solution(String s)
    {
        int answer = 1;

        int len = s.length();
        
        // 팰린드롬이 홀수인 경우
        for(int i=1;i<len-1;i++){
            int j=0;
            while(i-j>=0 && i+j<len){
                if(s.charAt(i-j) != s.charAt(i+j)){
                    break;
                }    
                j++;
            }
            answer = Math.max(answer, 1+((j-1)*2));
        }
        
        //팰린드롬이 짝수인 경우
        for(int i=0;i<len-1;i++){
            int j=0;
            while(i-j>=0 && i+j+1<len){
                if(s.charAt(i-j) != s.charAt(i+j+1)){
                    break;
                }
                j++;
            }
            answer = Math.max(answer, j*2);
        }

        return answer;
    }
}

위의 코드는 팰린드롬이 홀수인 경우와 짝수인 경우로 나누어 계산하였다.

또한, 각 경우에 대해 순차적으로 모든 경우를 계산하고 있기 때문에

O(N2)O(N^2)의 시간복잡도를 가지게 된다.

이 코드도 통과는 하지만 더 효율적인 방법이 있을 것 같다는 생각에 검색을 해보니 Manacher라는 알고리즘이 존재했다.

해당 알고리즘에 대한 설명은 블로그의 알고리즘 항목에 설명해두었다.

Manacher 알고리즘을 통해 아래와 같은 좀 더 효율적인 코드로 작성할 수 있었다.

최종 코드

java
import java.util.*;

class Solution
{
    public int solution(String s)
    {
        if(s.length()<=1){
            return s.length();
        }
        int answer = 0;
        int len = s.length();
        StringBuilder sb = new StringBuilder(len*2+3);

				//문자 처음, 끝, 사이 특수문자 추가
        sb.append("*");
        for(int i=0;i<len;i++){
            sb.append("#").append(s.charAt(i));
        }
        sb.append("#").append("@");
        
        char[] T = sb.toString().toCharArray();
        int tLen = T.length;
        
        int[] P = new int[tLen];
        int center = 0;
        int right = 0;

        for(int i=1;i<tLen-1;i++){
            int mirror = 2*center-i; // 현재 중심에 대한 대칭 인덱스
            
            // 이미 탐색된 범위 안이라면, 대칭 위치의 결과를 일부 복사
            if(i<right)
                P[i] = Math.min(right-i, P[mirror]);
            else
                P[i] = 0;
            
            // 좌우 확장
            while(T[i-1-P[i]] == T[i+1+P[i]])
                P[i]++;
            
            // right와 center 갱신
            if(i+P[i]>right){
                center = i;
                right = i+P[i];
            }
            
            // 최장 팰린드롬 길이 갱신
            answer = Math.max(answer, P[i]);
        }

        return answer;
    }
}

함께 읽으면 좋은 글

코딩 테스트2026-08-23

택배상자

order 배열은 택배 기사님이 원하는 상자 적재 순서다 기존 컨테이너 벨트는 1번부터 순서대로만 꺼낼 수 있다 보조 벨트는 스택처럼 마지막에 넣은 것부터 꺼낼 수 있다 원하는 순서대로 최대한 실을 수 있는 상자 개수를 구하는 문제다 처음에는 기존 벨트를 실제 리스트로 만들어…

코딩 테스트2026-08-23

롤케이크 자르기

topping 배열은 롤케이크에 일렬로 올라간 토핑 번호다 한 지점을 잘라 두 조각으로 나눴을 때, 양쪽 토핑 종류 수가 같아야 공평하게 나눈 것이다 공평하게 자를 수 있는 방법의 수를 구하는 문제다 처음에는 자르는 위치마다 왼쪽과 오른쪽 배열을 나눠서 각각 서로 다른 토핑…

코딩 테스트2026-08-23

할인 행사

want, number 배열로 정현이가 원하는 제품과 수량을 표현한다 discount 배열은 XYZ 마트가 매일 할인하는 제품 목록이다 연속된 10일 동안 할인 제품 종류와 수량이 want, number와 정확히 일치해야 회원가입할 수 있다 그런 시작일이 총 몇 번 있는지…

코딩 테스트2026-08-23

숫자 변환하기

자연수 x를 y로 바꾸는 데 x+n, x2, x3 세 가지 연산을 쓸 수 있다 x를 y로 바꾸는 최소 연산 횟수를 구하는 문제다 만들 수 없으면 -1을 반환한다 처음에는 x에서 시작해서 세 가지 연산을 재귀적으로 다 시도해보고 y에 도달하는 경로 중 가장 짧은 걸 고르면…