https://www.acmicpc.net/problem/9251
9251번: LCS
LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.
www.acmicpc.net
- LCS(Longest Common Subsequence, 최장 공통 부분 수열) 문제는 두 수열이 주어졌을 때 , 모두의 부분 수열이 된느 가장 긴 것을 찾는 문제
- 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.
- 입력으로 주어진 두 문자열의 LCS의 길이를 출력
풀이 과정
Longest Common Subsequence
[알고리즘 정리] 최장 공통 부분 수열(LCS) (tistory.com)
[알고리즘 정리] 최장 공통 부분 수열(LCS)
Logest Common Subequence 우리 말로 최장 공통 부분 수열이라고도 불리는 알고리즘이다. 어떤 문자열이 두 개 있을 때, 두 수열 사이에 있는 공통적인 문자들의 가장 긴 조합을 찾는 문제이다. 예를 들
jeonyeohun.tistory.com
[백준] 9251번 : LCS - JAVA [자바] (tistory.com)
[백준] 9251번 : LCS - JAVA [자바]
www.acmicpc.net/problem/9251 9251번: LCS LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAP
st-lab.tistory.com
- 최장 공통 부분 수열
- 어떤 문자열이 두 개 있을 때, 두 수열 사이에 있는 공통적인 문자들의 가장 긴 조합을 찾는 문제
ex)
X= (A, B, C, B, D, A, B)
Y= (B, D, C, A, B, A)
- 두 문자열 사이에는 많은 부분 문자열들이 있는데, 문자가 하나 뿐인 부분 문자열을 제외하고 모두 나열하면 다음과 같음
A,B
A,B,A
B,C
B,C,B
C,B
C,B,A
B,D
B,D,A
B,D,A,B
- 이 중에서 가장 긴 부분 문자열은 B,D,A,B가 됨
- 문제를 일반화하기 위해서 비교해야하는 문자열을 X=<x1,x2,..., xm>, Y={y1,y2,...,yn>라 하고, 두 문자열의 LCS를 Z={z1,z2,...,zk>라고 해 보자.
- 다음과 같은 명제가 성립한다고 할 수 있다.
1) xm = yn이라면, xm=ym=zk이고 새로운 LCS는 Xm-1와 Yn-1이라고 할 수 있다
2) xm != yn이라면, xm !=zk이고 새로운 LCS는 Xm-1와 Y이라고 할 수 있다.
3) xm != yn이라면, yn != zk이고 새로운 LCS는 X와 Yn-1이라고 할 수 있다.
- 만약 두 문자가 다르다고 한다면, 두 가지 경우를 생각할 수 있다.
- X 문자열의 길이를 줄이거나, Y 문자열의 길이를 줄이는 것이다.
- c[i,j]가 i,y 사이의 최대 부분 문자열 길이를 가지고 있다면, X와 Y의 문자가 같을 때, 바로 이전 최장 문자열의 길이에 1을 더한 값을 새로 저장하고, 두 문자가 다를 때는 X쪽 최장 문자열의 길이와 Y쪽 최장 문자열의 길이를 비교해서 더 큰 값을 가져온다.
- 위 계산식 대로 진행하면, 결국 똑같은 연산을 계속해서 해야하는 상황을 맞이한다.
- 따라서 한번 계산한 결과를 테이블에 저장해두고 재사용하는 방식을 시도해야 한다.
- 모든 X의 문자에 대해서 Y의 문자를 꺼내와 비교해서 위에서 작성했던 수식에 따라 값을 채워 넣자
- A를 만났을 때는 이전 값 중 제일 큰 0을 넣어주었다. 그리고 B를 만나게 되면 Xi와 Yj의 값이 같기 때문에 이전 위치의 가장 긴 길이인 0에 1을 더해 1로 채워주고 있다.
-C를 체크해보면 B와 C는 다른 값이기 때문에, X를 제외했을 떄, 즉 바로 왼쪽에 있는 값과, Y를 제외했을 때, 즉 좌측 대각선 위에 있는 값 중에 더 큰 값으로 배열을 채워주게 된다.
-이 논리대로 테이블을 모두 채워나가면 다음과 같이 표를 완성시킬 수 있다.
- LCS의 길이는 4이고, 해당 길이로 조합할 수 있는 부분 문자열은 총 3종류가 된다.
- LCS는 여러개가 나올 수 있고 표에서 최대값을 가지는 아이템의 갯수가 그 경우의 수를 의미하기 때문이다.
정답
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
static int memo[][] = new int [1001][1001];
public static void main(String[] args)throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
char[] s1 = br.readLine().toCharArray();
char[] s2 = br.readLine().toCharArray();
int len1 = s1.length;
int len2 = s2.length;
int memo[][] = new int[len1+1][len2+1];
for(int i=1; i<=len1;i++)
{
for(int j=1; j<=len2; j++)
{
//(i-1)과 (j-1)번쨰 문자가 서로 같다면
if(s1[i-1]==s2[j-1])
{
memo[i][j] = memo[i-1][j-1]+1;
}
else
{
//같지 않다면 이전 열(i-1)과 이전 행(j-1)의 값 중 큰 것으로 갱신
memo[i][j] = Math.max(memo[i-1][j],memo[i][j-1]);
}
}
}
bw.write(memo[len1][len2]+"");
bw.flush();
bw.close();
}
}
'Java > 백준' 카테고리의 다른 글
[JAVA] 백준 11659 구간 합 구하기 4 (0) | 2024.02.29 |
---|---|
[JAVA] 백준 12865 평범한 배낭 (0) | 2024.02.29 |
[JAVA] 백준 2565 전깃줄 (1) | 2024.02.28 |
[JAVA] 백준 11054 가장 긴 바이토닉 부분 수열 (1) | 2024.02.28 |
[JAVA] 백준 11053 가장 긴 증가하는 부분 수열 (0) | 2024.02.28 |