1230 문자열 거리
문제
문자열 O에서 문자열 N까지 문자열 거리는 O를 N과 같게 만들기 위해 필요한 문자열 삽입의 최솟값
이다. 문자열 삽입은 O의 어느 위치에서건 가능하다.
예를 들어, O가 “gosrl”일 때, ”sip gi”을 r이전에 삽입한다면 “gossip girl“이 된다.
문자열 O와 문자열 N이 주어질 때, 두 문자열의 거리를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 문자열 O, 둘째 줄에 문자열 N이 주어진다.
문자열의 길이는 최대 1,000이다.
문자열은 아스키 코드의 값이 32보다 크거나 같고, 126보다 작거나 같은 문자로만 이루어져 있다.
출력
첫째 줄에 문자열 O와 문자열 N의 문자열 거리를 출력한다. 만약 O를 N으로 만들 수 없다면 -1을 출력한다.
예제 입력 1
1 2
| hello fine hello, how are you? I'm fine thank you and you?
|
예제 출력 1
예제 입력 2
예제 출력 2
예제 입력 3
예제 출력 3
예제 입력 4
1 2
| abcefijklmnopuvwxz abcdefghijklmnopqrstuvwxyz
|
예제 출력 4
Solution
Expander
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import java.util.* import kotlin.math.min
private const val MAX = 1001
private var O: String = "" private var N: String = ""
private var DP = Array(MAX) { Array(MAX) { IntArray(2) { 0 } } }
fun main() { input() init() solve() }
private fun init() { DP[0][0][0] = 0 DP[0][0][1] = MAX for (i in 1 .. N.length) { DP[0][i][0] = MAX DP[0][i][1] = 1 } }
private fun input() = with(Scanner(System.`in`)) { O = nextLine() N = nextLine() }
private fun solve() { if (O.length > N.length) { println(-1) return }
for (i in 0 until O.length) { for (j in 0 .. i) { DP[i + 1][j][0] = MAX DP[i + 1][j][1] = MAX }
for (j in i until N.length) { if (O[i] == N[j]) { DP[i + 1][j + 1][0] = min(DP[i][j][0], DP[i][j][1]) } else { DP[i + 1][j + 1][0] = MAX } DP[i +1][j + 1][1] = min(DP[i + 1][j][0] + 1, DP[i + 1][j][1]) } }
val result = min(DP[O.length][N.length][0], DP[O.length][N.length][1]) if (result >= MAX) { println(-1) } else { println(result) } }
|
Point of Thinking
- 문자열
O
를 split해서 동일한 문자열을 치환해 나간 뒤, 이를 중복 제거한 다음 합계를 구하면 답이 나올 것이라고 생각했다.
- 하지만 입력값의 범위가 아스키 코드 32 ~ 126이므로 치환 방법은 사용할 수가 없고, 결국 동적계획법으로 풀이해야 한다.
- 문자열 양극 혹은 내부에 문자열을 넣는 것이므로, 넣을 수 있냐 없냐에 따라 최솟값을 갱신해나가는 식으로 처리해야 한다.
- 문자열 길이가 1000자라서 모든 문자를 순회하는 식으로 점화식을 짰는데 다행히 Accepted되었다.
- 메모리 이슈가 있긴 했는데 Integer를 Short로 치환했다가, 로직을 개선해서 다시 Integer로 Accepted.