어떤 문자열이 팰린드롬인지 확인하는 2가지 방법 --> O(N)
- s == reverse(s) 인지 확인
- 모든 ch[i] == ch[s.length-i] 인지 확인
이 때, 쿼리의 갯수가 M개이므로 총 걸리는 시간은 O(MN)인데 시간 제한에 걸린다.
팰린드롬을 검사하는 다른 방법
- 길이가 1인 부분 수열은 반드시 팰린드롬 --> O(N)
- 길이가 2인 부분 수열은 두 수가 같을 때만 팰린드롬 --> O(N)
- 길이가 3이상인 경우는 DP를 이용한다.-->O(N^2)
- DP[i][j]: i ~ j까지 팰린드롬인지 아닌지 저장
- ch[i] == ch[j]이면 DP[i][j] = DP[i+1][j-1]이다.
=> O(N^2+M)만에 구할 수 있다.
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
int n = Integer.parseInt(br.readLine());
int arr[] = new int[n + 1];
st = new StringTokenizer(br.readLine());
for (int i = 1; i <= n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
int dp[][] = new int[n + 1][n + 1];
dp = calcPalindrome(arr, n);
int m = Integer.parseInt(br.readLine());
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
bw.write(dp[start][end] + "\n");
}
bw.flush();
bw.close();
}
public static int[][] calcPalindrome(int arr[], int n) {
int dp[][] = new int[n + 1][n + 1];
// 길이가 1일 때
for (int i = 1; i <= n; i++) {
dp[i][i] = 1;
}
// 길이가 2일 때
for (int i = 1; i <= n - 1; i++) {
if (arr[i] == arr[i + 1]) {
dp[i][i + 1] = 1;
}
}
// 길이가 3 이상
for (int i = 3; i <= n; i++) {
for (int j = 1; j <= n - i + 1; j++) {
int k = j + i - 1;
if (arr[j] == arr[k] && dp[j + 1][k - 1] == 1) {
dp[j][k] = 1;
}
}
}
return dp;
}
}
'알고리즘 공부 > boj' 카테고리의 다른 글
boj 11066: 파일 합치기 (0) | 2020.07.21 |
---|---|
boj 1509: 팰린드롬 분할 (0) | 2020.07.21 |
boj 1890: 점프 (0) | 2020.07.20 |
boj 11660: 구간 합 구하기 5 (0) | 2020.07.19 |
boj 1197: 최소 스패닝 트리 (0) | 2020.07.19 |