유명한 최장부분 공통수열 문제. 아이디어를 떠올리지 못해 구글링을 하였다.
이때, dp배열의 정의는 i, j번째 문자열 원소까지 비교하였을 때 LCS의 길이이다.
s1[0]과 s2[0]을 비교한 값은 dp[1][1]에 들어가므로 인덱스 보정에 유의해야 한다.
그림을 그려보면 이해가 쉽다. 같은 문자가 나오면 바로 이전까지의 공통부분+1을 해주고, 두 문자를 비교했을 때 다르면 두 대각선 사이 중 큰 것을 출력해주면 된다.
풀어서 설명해보겠다.
우선 경우는 크게 두가지로 나눌 수 있다.
1. i번째 인덱스의 문자와 j번째 인덱스의 문자가 같을 때:
이때는 공통부분이 생겼기에 아무런 문제 없이 배열을 업데이트 하면된다.
dp[i+1][j+1] = dp[i][j] +1
2. i번째 인덱스의 문자와 j번째 인덱스의 문자가 같지 않을 때:
이 경우에는 세가지 경우가 존재한다.
2-1. i번째 인덱스와 j-1번째 인덱스를 비교한 값이 더 클때
2-2. i-1번째 인덱스와 j번재 인덱스를 비교한 값이 더 클때
2-3. 위의 두 결과값이 같을 때(i~i-1, j~j-1 에 LCS 해당사항 없음)
이때 2-3은 경계상황이기에 둘중 하나에 포함시켜줄 수 있다.
현재는 최대 길이를 구하는 것이기에 2-1, 2-2, 2-3 중 최댓값만을 취하면 되는 것이다.
코드는 다음과 같다.
#include<iostream>
using namespace std;
int dp[1001][1001];
int main(){
string s1, s2;
cin>>s1>>s2;
int n=s1.length(), m=s2.length();
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(s1[i]==s2[j]){
dp[i+1][j+1]=dp[i][j]+1;
} else {
dp[i+1][j+1]=max(dp[i][j+1], dp[i+1][j]);
}
}
} cout<<dp[n][m];
}
'알고리즘' 카테고리의 다른 글
| Boj 1912 c++ 연속합 (0) | 2025.07.19 |
|---|---|
| Boj 11404 c++ 플로이드 워셜 (1) | 2025.07.17 |
| Boj 9465 c++ 스티커 (0) | 2025.07.16 |
| Boj 1932 c++ 정수 삼각형 (0) | 2025.07.15 |
| Boj 15666 c++ N과 M(12) (0) | 2025.07.14 |