본문으로 바로가기

백준 09252 - LCS 2

category BOJ 백준Dynamic Programming 4년 전

출처 : https://www.acmicpc.net/problem/9252 

 

9252번: LCS 2

LCS(Longest Common Subsequence, 최장 공통 부분 수열)문제는 두 수열이 주어졌을 때, 모두의 부분 수열이 되는 수열 중 가장 긴 것을 찾는 문제이다. 예를 들어, ACAYKP와 CAPCAK의 LCS는 ACAK가 된다.

www.acmicpc.net

 

고려사항

  • 동적 프로그래밍 LCS 알고리즘을 응용하여 제일 긴 부분 문자열의 요소들을 뽑아내는 문제.
  • lcs 를 재귀로 풀 수도 있고( 09251 - LCS ), 이 문제처럼 bottom -> top 으로 반복문으로도 풀 수 있다.
    재귀는 top -> down 이다!
  • 현재 조사중인 str1 의 인덱스 y 와 str2의 인덱스 x 들의 문자가 같으면 lcs[y-1][x-1] + 1,
    다르면 lcs[y-1][x], lcs[y][x-1] 중 큰 값으로 기입을 해가며 lcs 를 채워나가면,
    lcs[str1Len][str2Len] 의 값이 가장 긴 부분 문자열의 길이 이다.
    (str의 인덱스는 0부터 시작하지만, lcs를 편하게 채우기 위해서 보통 첫 행과 첫 열은 0으로 패딩해주기 때문에
    인덱스 계산에 주의하자!!!!!!)

  • 문자열 길이를 구하고 나서는, 각각의 요소들을 뽑기 위해선, lcs[str1Len][str2Len] 부터,
    str1[y] == str2[x] 라면 정답 문자열에 원소를 추가하고 두 인덱스 모두 -1 해주고,
    서로 다르다면 lcs[y-1][x], lcs[y][x-1] 중 lcs[y][x] 와 같은 값을 지닌 방향으로 인덱스를 수정해주며
    lcs값이 0이 될 때까지 진행해 주면 된다.
    ( 앞에서 가장 긴 부분 문자열 길이리를 구했던 방식을 되돌아가는 방식이다! )
  • 정답 문자열을 뒤집어서 출력해주면 끝!

 

#include <iostream>
#include <algorithm>
using namespace std;
int lcs[1001][1001];
int main() {
string str1, str2, ans;
int maxLen, str1Len, str2Len, y, x;
cin>>str1>>str2;
str1Len = str1.length();
str2Len = str2.length();
y = str1Len;
x = str2Len;
for(int i=0;i<str1Len;++i){
for(int j=0;j<str2Len;++j){
if(str1[i] == str2[j]){
lcs[i+1][j+1] = lcs[i][j] + 1;
}else{
lcs[i+1][j+1] = max(lcs[i][j+1], lcs[i+1][j]);
}
}
}
maxLen = lcs[str1Len][str2Len];
cout<<maxLen<<"\n";
if(maxLen){
while(lcs[y][x] != 0){
if(str1[y-1] == str2[x-1]){
ans.push_back(str1[y-1]);
--y, --x;
}else{
if(lcs[y-1][x] == lcs[y][x]){
--y;
}else{
--x;
}
}
}
reverse(ans.begin(), ans.end());
cout<<ans;
}
return 0;
}

BOJ 백준Dynamic Programming카테고리의 다른글

백준 12852 - 1로 만들기 2  (0) 2021.01.04
백준 02407 - 조합  (0) 2020.11.15
백준 11660 - 구간 합 구하기 5  (0) 2020.11.14
백준 02156 - 포도주 시식  (0) 2020.10.27
백준 10844 - 쉬운 계단 수  (0) 2020.10.26