백준/그리디

백준 30805 c++ "사전 순 최대 공통 부분 수열" -PlusUltraCode-

PlusUltraCode 2025. 5. 9. 12:31

https://www.acmicpc.net/problem/30805

 

[필자 사고]

일단 사전순에서 가장 느리게 되려면 앞 부분에 가장 큰수가 와야 된다.

이러한 사고과정의 형태로 정렬을 이용할 수 있ㄷ.

 

두번째 문제 해당 부분은 수열이다. 공통 부분 수열은 인덱스 순서를 중요시 한다.

그래서 같은 숫자일 경우 인덱스가 작은거 먼저 와야 더 늦은 사전 순을 만들 수 있다.

 

만든 배열을 잘 정렬한 뒤 이제 i,j를 이용하여 각 idx의 값들을 비교해야 한다.

같은 경우 resultArr에 값을 넣고 lastIdx 도 갱신해준다.

 

나머지 부분은 첫번째 배열 수보다 두번째 배열 수가 크거나 작다면 갱신해주고 또한 lastIdx보다 작은 인덱스라면 

\검사할 필요없이 바로 인덱스를 증가시키는 형태로 해당 문제를 풀었다.

[코드 해설]

2. 두 시퀀스 비교 및 결과 추출 (Game_Start 함수)

Game_Start() 함수는 arr1과 arr2 두 시퀀스를 탐색하며 조건에 맞는 공통 원소를 추출하는 로직을 수행합니다.

먼저 i, j 두 포인터를 0으로 초기화하여 각각 arr1, arr2의 현재 탐색 위치를 나타냅니다.
또한, lastIdx1, lastIdx2는 직전에 매칭된 원소의 인덱스를 기억하기 위한 변수이며, 초기값은 -1입니다.

while 루프를 통해 두 시퀀스를 끝까지 탐색하며 다음 조건을 평가합니다:

  • arr1[i].first > arr2[j].first 또는 arr1[i].second < lastIdx1이면 i 증가
    → 현재 arr1[i]가 너무 크거나, 이미 사용된 인덱스보다 앞에 있는 경우 건너뜀
  • arr2[j].first > arr1[i].first 또는 arr2[j].second < lastIdx2이면 j 증가
    → arr2[j]가 너무 크거나, 이전 인덱스보다 앞이면 건너뜀
  • 그렇지 않다면, 두 원소의 값이 같고, 정렬 순서상 조건도 맞으면
    → arr1[i].first를 결과 벡터에 추가하고, lastIdx1, lastIdx2를 현재 인덱스로 갱신한 뒤 i, j 모두 증가

이렇게 함으로써 두 정렬된 시퀀스에서 공통된 값을 조건에 맞게 순서대로 추출하게 됩니다.

마지막으로, 결과 벡터의 크기(= 매칭된 원소 수)를 출력하고, 결과 벡터의 내용을 공백으로 구분하여 출력합니다.

[소스 코드]

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int N, M;
typedef pair<int, int> Node;
vector<Node> arr1, arr2;

bool cmp(Node a, Node b) {
	if (a.first == b.first) {
		return a.second < b.second;
	}
	return a.first > b.first;
}

void Input() {
	cin >> N;
	for (int i = 0; i < N; i++) {
		int num;
		cin >> num;
		arr1.push_back({ num ,i});
	}

	cin >> M;
	for (int i = 0; i < M; i++) {
		int num;
		cin >> num;
		arr2.push_back({ num ,i});
	}
	sort(arr1.begin(), arr1.end(), cmp);
	sort(arr2.begin(), arr2.end(), cmp);
}

void Game_Start() {
	int i = 0, j = 0;
	int lastIdx1 = -1, lastIdx2 = -1;
	vector<int> resultArr;

	while (i < N && j < M) {
		if (arr1[i].first > arr2[j].first || arr1[i].second < lastIdx1) {
			++i;
		}
		else if (arr2[j].first > arr1[i].first || arr2[j].second < lastIdx2) {
			++j;
		}
		else {
			resultArr.push_back(arr1[i].first);
			lastIdx1 = arr1[i].second;
			lastIdx2 = arr2[j].second;
			++i;
			++j;
		}
	}

	cout << resultArr.size() << '\n';
	for (int x : resultArr) {
		cout << x << ' ';
	}
	
}

int main(void) {
	Input();
	Game_Start();
}