-
백준 9252 LCS 2Algorithm/BOJ 2021. 4. 20. 11:25728x90
출처: www.acmicpc.net/problem/9252
분류: LCS
접근방식
최장 증가 수열을 찾는 전통적인 LCS 문제입니다.
문자열을 그대로 사용하면 시간초과가 나서 길이 테이블을 완성하고 백트래킹을 통해 문자열을 찾아주는 방식으로 해결했습니다.
LCS는 다음과 같이 두 문자열로 이차원 행렬을 완성시켜 나가는 방식으로 찾아줄 수 있습니다.
현재 칸의 두 문자열의 문자가 같다면 왼쪽 대각선 위의 문자열에 현재 문자를 붙여나갑니다.
다르다면 위나 왼쪽 중에서 더 큰 문자열을 가져옵니다. 같다면 모두 가능한 문자열이겠죠?
이 원리를 이용해 저희 예제로 만들어보면
가로 CAPCAK
세로 ACAYKP
로 두면 다음과 같은 LCS 테이블을 만들 수 있습니다.
이제 마지막으로 마지막부터 백트래킹으로 문자열을 만들어봐야겠네요.
했던 과정을 거꾸로 돌아간다고 생각하면 됩니다.
해당 칸의 문자가 같다면 역시 왼쪽 위 대각선으로 돌아가면서 해당 칸의 문자를 붙여서 리턴,
아니라면 더 큰쪽으로 이동하고 다시 탐색해나가면 됩니다.
func backtrackLcs(r: Int, c: Int) -> String { if lcsTable[r][c] == 0 { return "" } else if rowStr[r-1] == colStr[c-1] { return backtrackLcs(r: r-1, c: c-1) + String(rowStr[r-1]) } else if lcsTable[r-1][c] > lcsTable[r][c-1] { return backtrackLcs(r: r-1, c: c) } else { return backtrackLcs(r: r, c: c-1) } }
해결방법
let rowStr = Array(readLine()!) let colStr = Array(readLine()!) var lcsTable = [[Int]](repeating: [Int](repeating: 0, count: colStr.count+1), count: rowStr.count+1) for r in 1..<rowStr.count+1 { for c in 1..<colStr.count+1 { if colStr[c-1] == rowStr[r-1] { lcsTable[r][c] = lcsTable[r-1][c-1]+1 } else { lcsTable[r][c] = max(lcsTable[r][c-1], lcsTable[r-1][c]) } } } func backtrackLcs(r: Int, c: Int) -> String { if lcsTable[r][c] == 0 { return "" } else if rowStr[r-1] == colStr[c-1] { return backtrackLcs(r: r-1, c: c-1) + String(rowStr[r-1]) } else if lcsTable[r-1][c] > lcsTable[r][c-1] { return backtrackLcs(r: r-1, c: c) } else { return backtrackLcs(r: r, c: c-1) } } print(lcsTable[rowStr.count][colStr.count]) if lcsTable[rowStr.count][colStr.count] != 0 { print(backtrackLcs(r: rowStr.count, c: colStr.count)) }
배운점
'Algorithm > BOJ' 카테고리의 다른 글
백준 11049 행렬 곱셈 순서 (0) 2021.04.21 백준 17070 파이프 옮기기 1 (0) 2021.04.20 백준 2096 내려가기 (0) 2021.04.20 백준 1915 가장 큰 정사각형 (0) 2021.04.19 백준 1937 욕심쟁이 판다 (0) 2021.04.19