fun main(args: Array<String>) {
    val S = readLine()!!
    val T = readLine()!!

    // LCS を記録するメモ配列を初期化
    val dp = Array(3001) { IntArray(3001) { 0 } }

    // 二重ループで メモを埋めていく
    for (i in 1..S.length) {
        for (j in 1..T.length) {
            // 条件に従って メモ配列を更新 (文字列のインデックスと配列のインデックスは１つ違う）
            if (S[i - 1] == T[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1
            } else
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])
        }
    }

    // LCS の再構成, d[S.length][T.length] から逆にたどって，斜め遷移をしてきてる部分を出力すれば良い？？
    // ある地点までで，同じ値になるたどり着き方(max の操作で選択されないことがないパス）がすなわち，LCSのパターン数になる
    // そのうち１つを逆にたどっていった結果を出力すればよい

    // 1. 斜め上を見て現在の値 -1 かどうか判定 ( -1 であればそちらへ遷移，文字列キューにプッシュ・そうでないなら２の処理へ),
    // 2. 左か上を見て，現在の値と同じかどうか判定, 同じ方へ遷移（文字列には加えない

    var indexI = S.length
    var indexJ = T.length
    var ans = ""

    // どちらかのインデックスが 0 になるまで遷移していく
    while (indexI != 0 && indexJ != 0) {

        // まず一致していかった場合を確認
        if (dp[indexI - 1][indexJ] == dp[indexI][indexJ]) {
            indexI -= 1
            continue
        }
        if (dp[indexI][indexJ - 1] == dp[indexI][indexJ]) {
            indexJ -= 1
            continue
        }

        // 文字列が一致していたとして答えに追加
        ans = S[indexI - 1] + ans
        indexI -= 1
        indexJ -= 1
    }
    println(ans)
}