/** * file: memLcsMaximizer.kt * author: San Skulrattanakulchai * date: 2018-11-02 * * This program differs from `memLcs.kt` in that it uses both the * `opt` table and the maximizer table `maxer`. */ fun main(args: Array) { val x = readLine()!! val y = readLine()!! fun String.explode() = this.toList().joinToString(separator=" ") println(""" |x: ${x.explode()} |y: ${y.explode()} |LCS(x, y): ${memLcs(x, y).explode()} """.trimMargin()) } enum class Dir { NONE, RIGHT, DOWN, DIAG } fun memLcs(x: String, y: String): String { val UNKNOWN = -1 val m = x.length val n = y.length val opt = Array(m+1) { i -> IntArray(n+1) { j -> when { i == m -> 0 j == n -> 0 else -> UNKNOWN } } } val maxer = Array>(m) { Array(n) { Dir.NONE } } /* Use this function **whenever you want to read opt[i][j]**. */ fun accessTable(i: Int, j: Int): Int { if (opt[i][j] == UNKNOWN) { if (x[i] == y[j]) { opt[i][j] = accessTable(i+1, j+1) + 1 maxer[i][j] = Dir.DIAG } else if (accessTable(i+1, j) > accessTable(i, j+1)) { opt[i][j] = opt[i+1][j] maxer[i][j] = Dir.DOWN } else { opt[i][j] = opt[i][j+1] maxer[i][j] = Dir.RIGHT } } return opt[i][j] } fun lcs(): String { accessTable(0, 0) val sb = StringBuilder() var i = 0 var j = 0 while ((i < m) && (j < n)) { when (maxer[i][j]) { Dir.DIAG -> { sb.append(x[i]) i++ j++ } Dir.DOWN -> i++ Dir.RIGHT -> j++ else -> throw Exception("Incorrect maximizer value.") } } return sb.toString() } return lcs() }