가장 긴 팰린드롬
문제 풀이 시간 :
문제 요약
- 문자열 s(길이 2,500 이하, 소문자만) 이 주어짐
- 앞뒤가 같은 부분 문자열(팰린드롬) 중 가장 길이가 긴 것의 길이를 구해야 함
- 즉, s의 부분문자열 중에서 좌우 대칭이 되는 가장 긴 구간의 길이를 찾는 문제
문제 풀이
이 문제는 처음보고 푼 방식이 순차탐색이었다.
초기 코드
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;
}
}위의 코드는 팰린드롬이 홀수인 경우와 짝수인 경우로 나누어 계산하였다.
또한, 각 경우에 대해 순차적으로 모든 경우를 계산하고 있기 때문에
의 시간복잡도를 가지게 된다.
이 코드도 통과는 하지만 더 효율적인 방법이 있을 것 같다는 생각에 검색을 해보니 Manacher라는 알고리즘이 존재했다.
해당 알고리즘에 대한 설명은 블로그의 알고리즘 항목에 설명해두었다.
Manacher 알고리즘을 통해 아래와 같은 좀 더 효율적인 코드로 작성할 수 있었다.
최종 코드
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;
}
}함께 읽으면 좋은 글
택배상자
order 배열은 택배 기사님이 원하는 상자 적재 순서다 기존 컨테이너 벨트는 1번부터 순서대로만 꺼낼 수 있다 보조 벨트는 스택처럼 마지막에 넣은 것부터 꺼낼 수 있다 원하는 순서대로 최대한 실을 수 있는 상자 개수를 구하는 문제다 처음에는 기존 벨트를 실제 리스트로 만들어…
롤케이크 자르기
topping 배열은 롤케이크에 일렬로 올라간 토핑 번호다 한 지점을 잘라 두 조각으로 나눴을 때, 양쪽 토핑 종류 수가 같아야 공평하게 나눈 것이다 공평하게 자를 수 있는 방법의 수를 구하는 문제다 처음에는 자르는 위치마다 왼쪽과 오른쪽 배열을 나눠서 각각 서로 다른 토핑…
할인 행사
want, number 배열로 정현이가 원하는 제품과 수량을 표현한다 discount 배열은 XYZ 마트가 매일 할인하는 제품 목록이다 연속된 10일 동안 할인 제품 종류와 수량이 want, number와 정확히 일치해야 회원가입할 수 있다 그런 시작일이 총 몇 번 있는지…
숫자 변환하기
자연수 x를 y로 바꾸는 데 x+n, x2, x3 세 가지 연산을 쓸 수 있다 x를 y로 바꾸는 최소 연산 횟수를 구하는 문제다 만들 수 없으면 -1을 반환한다 처음에는 x에서 시작해서 세 가지 연산을 재귀적으로 다 시도해보고 y에 도달하는 경로 중 가장 짧은 걸 고르면…