어떤 수열이 다른 수열의 부분 수열이라는 것은 다음을 의미합니다.
또한, 어떤 수열이 다른 수열보다 사전 순으로 나중이라는 것은 다음을 의미합니다.
양의 정수로 이루어진 길이가 인 수열 이 주어집니다. 마찬가지로 양의 정수로 이루어진 길이가 인 수열 이 주어집니다.
수열 와 수열 가 공통으로 갖는 부분 수열들 중 사전 순으로 가장 나중인 것을 구하세요.
첫 줄에 수열 의 길이 이 주어집니다.
둘째 줄에 개의 양의 정수 이 주어집니다.
셋째 줄에 수열 의 길이 이 주어집니다.
넷째 줄에 개의 양의 정수 이 주어집니다.
와 의 공통 부분 수열 중 사전 순으로 가장 나중인 수열의 크기 를 출력하세요.
이라면, 다음 줄에 개의 수를 공백으로 구분해 출력하세요. 번째 수는 와 의 공통 부분 수열 중 사전 순으로 가장 나중인 수열의 번째 수입니다.
import sys
input = sys.stdin.readline
n = int(input())
list1 = list(map(int, input().split()))
m = int(input())
list2 = list(map(int, input().split()))
dp = [[0]*(m+1) for _ in range(n+1)]
for i in range(1, n+1):
for j in range(1, m+1):
if list1[i-1]==list2[j-1]:
dp[i][j] = dp[i-1][j-1]+1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
max1 = dp[n][m]
common = []
for i in range(max1):
id = dp[-1].index(i+1)
common.append(list2[id-1])
max2 = max(common)
id = common.index(max2)
answer = common[id:]
print(len(answer))
print(*answer)
위는 LCS를 이용해서 풀어보려다가 오답 처리된 코드이다. 하지만 어느 반례 때문에 실패한 것인지 잘 모르겠다...
아래는 다른 풀이를 참고하여 고쳐 풀어서 정답을 받은 코드이다.
import sys
input = sys.stdin.readline
n = int(input())
list1 = list(map(int, input().split()))
m = int(input())
list2 = list(map(int, input().split()))
common = set(list1)&set(list2)
answer = []
while common:
max1 = max(common)
answer.append(max1)
idx1 = list1.index(max1)
idx2 = list2.index(max1)
list1 = list1[idx1+1:]
list2 = list2[idx2+1:]
common = set(list1)&set(list2)
print(len(answer))
print(*answer)
결국에는 사전 순으로 가장 나중인 것을 구해야 하므로 처음부터 정석적으로 최장 공통 수열을 구할 필요는 없다. 우선 두 수열에서 공통인 수들을 뽑아내서 max 값을 기준으로 common 배열이 빌 때까지 인덱싱을 하며 공통 부분이 있는지 반복적으로 찾으면 두 수열의 공통 부분 수열 중 사전 순으로 가장 나중인 것을 찾을 수 있게 된다.
https://www.acmicpc.net/problem/30805
https://code-angie.tistory.com/63