#include <algorithm>
#include <array>
#include <bits/stdc++.h>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <vector>

// lib/rotate_left.hpp
#ifndef ROTATE_LEFT_HPP
#define ROTATE_LEFT_HPP


/*
usage:

// 5-bit circular shift to the left
tools::rotate_left(x, 5);
*/

// Source: Stack Overflow ( https://stackoverflow.com/questions/776508/best-practices-for-circular-shift-rotate-operations-in-c/776523#776523 )
// Author: John Regehr ( https://blog.regehr.org/ ) and Peter Cordes ( https://stackoverflow.com/users/224132/peter-cordes )
// License: CC BY-SA 3.0
namespace tools {
  template <typename T, typename ::std::enable_if<::std::is_unsigned<T>::value, ::std::nullptr_t>::type = nullptr>
  constexpr T rotate_left(const T& value, const ::std::size_t& count) noexcept {
    return (value << (count & ::std::numeric_limits<T>::max())) | (value >> (-(count & ::std::numeric_limits<T>::max()) & ::std::numeric_limits<T>::max()));
  }

  template <typename T, typename ::std::enable_if<::std::is_signed<T>::value, ::std::nullptr_t>::type = nullptr>
  T rotate_left(const T& value, const ::std::size_t& count) {
    return value >= static_cast<T>(0)
      ? static_cast<T>(::tools::rotate_left(static_cast<typename ::std::make_unsigned<T>::type>(value), count))
      : (throw ::std::invalid_argument("value of ::tools::rotate_left must be non-negative, but was " + ::std::to_string(value) + "."));
  }
}

#endif

// lib/util.hpp
#ifndef UTIL_HPP
#define UTIL_HPP


typedef ::std::int_fast64_t i64;
typedef ::std::uint_fast64_t u64;
typedef ::std::int_fast32_t i32;
typedef ::std::uint_fast32_t u32;

namespace tools {
  template <typename T>
  void read(::std::istream& is, ::std::vector<T>& vector, const typename ::std::vector<T>::size_type size) {
    vector.reserve(size);
    ::std::copy_n(::std::istream_iterator<T>(is), size, ::std::back_inserter(vector));
  }
  template <typename T>
  void read(::std::vector<T>& vector, const typename ::std::vector<T>::size_type size) {
    ::tools::read(::std::cin, vector, size);
  }

  template <typename T, ::std::size_t N>
  void read(::std::istream& is, ::std::array<T, N>& array) {
    ::std::copy_n(std::istream_iterator<T>(is), N, array.begin());
  }
  template <typename T, ::std::size_t N>
  void read(::std::array<T, N>& array) {
    ::tools::read(::std::cin, array);
  }
}

#endif

// lib/vector2.hpp
#ifndef VECTOR2_HPP
#define VECTOR2_HPP


/*
usage:

tools::vector2<int>(6, 5) // => (6, 5)
*/

namespace tools {
  template <typename T>
  class vector2 {
  public:
    T x;
    T y;

    vector2() :
      vector2(T(), T()) {
    }

    vector2(const T& x, const T& y) :
      x(x),
      y(y) {
    }

    double norm() const {
      return ::std::sqrt(this->squaredNorm());
    }

    T squaredNorm() const {
      return this->inner_product(*this);
    }

    template <typename SFINAE_T = T, typename ::std::enable_if<::std::is_same<SFINAE_T, double>::value, ::std::nullptr_t>::type = nullptr>
    double normalize() const {
      return *this / this->norm();
    }

    ::tools::vector2<T> operator+() const {
      return *this;
    }

    ::tools::vector2<T> operator-() const {
      return ::tools::vector2<T>(-this->x, -this->y);
    }

    friend ::tools::vector2<T> operator+(const ::tools::vector2<T>& lhs, const ::tools::vector2<T>& rhs) {
      return ::tools::vector2<T>(lhs.x + rhs.x, lhs.y + rhs.y);
    }

    friend ::tools::vector2<T> operator-(const ::tools::vector2<T>& lhs, const ::tools::vector2<T>& rhs) {
      return ::tools::vector2<T>(lhs.x - rhs.x, lhs.y - rhs.y);
    }

    template <typename OTHER, typename ::std::enable_if<!::std::is_same<OTHER, ::tools::vector2<T>>::value, ::std::nullptr_t>::type = nullptr>
    friend ::tools::vector2<T> operator*(const ::tools::vector2<T>& lhs, const OTHER& rhs) {
      return ::tools::vector2<T>(lhs.x * rhs, lhs.y * rhs);
    }
    template <typename OTHER, typename ::std::enable_if<!::std::is_same<OTHER, ::tools::vector2<T>>::value, ::std::nullptr_t>::type = nullptr>
    friend ::tools::vector2<T> operator*(const OTHER& lhs, const ::tools::vector2<T>& rhs) {
      return ::tools::vector2<T>(lhs * rhs.x, lhs * rhs.y);
    }

    template <typename OTHER, typename ::std::enable_if<!::std::is_same<OTHER, ::tools::vector2<T>>::value, ::std::nullptr_t>::type = nullptr>
    friend ::tools::vector2<T> operator/(const ::tools::vector2<T>& lhs, const OTHER& rhs) {
      return ::tools::vector2<T>(lhs.x / rhs, lhs.y / rhs);
    }

    T inner_product(const ::tools::vector2<T>& other) const {
      return this->x * other.x + this->y * other.y;
    }

    ::tools::vector2<T>& operator+=(const ::tools::vector2<T>& other) {
      return *this = *this + other;
    }

    ::tools::vector2<T>& operator-=(const ::tools::vector2<T>& other) {
      return *this = *this - other;
    }

    template <typename OTHER, typename ::std::enable_if<!::std::is_same<OTHER, ::tools::vector2<T>>::value, ::std::nullptr_t>::type = nullptr>
    ::tools::vector2<T>& operator*=(const OTHER& other) {
      return *this = *this * other;
    }

    template <typename OTHER, typename ::std::enable_if<!::std::is_same<OTHER, ::tools::vector2<T>>::value, ::std::nullptr_t>::type = nullptr>
    ::tools::vector2<T>& operator/=(const OTHER& other) {
      return *this = *this / other;
    }

    friend bool operator==(const ::tools::vector2<T>& lhs, const ::tools::vector2<T>& rhs) {
      return lhs.x == rhs.x && lhs.y == rhs.y;
    }

    friend bool operator!=(const ::tools::vector2<T>& lhs, const ::tools::vector2<T>& rhs) {
      return lhs.x != rhs.x || lhs.y != rhs.y;
    }

    static ::std::array<::tools::vector2<T>, 4> four_directions() {
      return ::std::array<::tools::vector2<T>, 4>({
        ::tools::vector2<T>(static_cast<T>(-1), static_cast<T>(0)),
        ::tools::vector2<T>(static_cast<T>(1), static_cast<T>(0)),
        ::tools::vector2<T>(static_cast<T>(0), static_cast<T>(-1)),
        ::tools::vector2<T>(static_cast<T>(0), static_cast<T>(1))
      });
    }

    static ::std::array<::tools::vector2<T>, 8> eight_directions() {
      return ::std::array<::tools::vector2<T>, 8>({
        ::tools::vector2<T>(static_cast<T>(-1), static_cast<T>(-1)),
        ::tools::vector2<T>(static_cast<T>(-1), static_cast<T>(0)),
        ::tools::vector2<T>(static_cast<T>(-1), static_cast<T>(1)),
        ::tools::vector2<T>(static_cast<T>(0), static_cast<T>(-1)),
        ::tools::vector2<T>(static_cast<T>(0), static_cast<T>(1)),
        ::tools::vector2<T>(static_cast<T>(0), static_cast<T>(-1)),
        ::tools::vector2<T>(static_cast<T>(1), static_cast<T>(-1)),
        ::tools::vector2<T>(static_cast<T>(1), static_cast<T>(0)),
        ::tools::vector2<T>(static_cast<T>(1), static_cast<T>(1))
      });
    }
  };
}

namespace std {
  template <typename T>
  ::std::string to_string(const ::tools::vector2<T>& f) {
    return '(' + ::std::to_string(f.x) + ", " + ::std::to_string(f.y) + ')';
  }

  template <typename T>
  struct hash<::tools::vector2<T>> {
    using result_type = ::std::size_t;
    using argument_type = ::tools::vector2<T>;
    ::std::size_t operator()(const ::tools::vector2<T>& key) const {
      static const ::std::hash<T> hash;
      static const ::std::size_t shift = ::std::numeric_limits<::std::size_t>::digits / 2;
      const ::std::size_t hash_x = hash(key.x);
      const ::std::size_t hash_y = hash(key.y);
      return hash_x ^ ::tools::rotate_left(hash_y, shift);
    }
  };

  template <typename T>
  ::std::ostream& operator<<(::std::ostream& os, const ::tools::vector2<T>& self) {
    return os << ::std::to_string(self);
  }

  template <typename T>
  ::std::istream& operator>>(::std::istream& is, ::tools::vector2<T>& self) {
    return is >> self.x >> self.y;
  }
}

#endif

// main.cpp

int main() {
  std::string s, t;
  std::cin >> s >> t;
  const i64 s_size = s.size();
  const i64 t_size = t.size();
  std::vector<std::vector<i64>> dp(s_size + 1, std::vector<i64>(t_size + 1, std::numeric_limits<i64>::min()));
  std::vector<std::vector<tools::vector2<i64>>> prev(s_size + 1, std::vector<tools::vector2<i64>>(t_size + 1));
  dp[0][0] = 0;
  for (i64 i = 0; i <= s_size; ++i) {
    for (i64 j = 0; j <= t_size; ++j) {
      if (i < s_size && j < t_size && s[i] == t[j] && dp[i + 1][j + 1] < dp[i][j] + 1) {
        dp[i + 1][j + 1] = dp[i][j] + 1;
        prev[i + 1][j + 1] = tools::vector2<i64>(i, j);
      }
      if (i + 1 <= s_size && dp[i + 1][j] < dp[i][j]) {
        dp[i + 1][j] = dp[i][j];
        prev[i + 1][j] = tools::vector2<i64>(i, j);
      }
      if (j + 1 <= t_size && dp[i][j + 1] < dp[i][j]) {
        dp[i][j + 1] = dp[i][j];
        prev[i][j + 1] = tools::vector2<i64>(i, j);
      }
    }
  }

  std::string answer = "";
  for (tools::vector2<i64> pos(s_size, t_size); pos != tools::vector2<i64>(0, 0);) {
    const tools::vector2<i64> prev_pos = prev[pos.x][pos.y];
    if (prev_pos.x < pos.x && prev_pos.y < pos.y) {
      answer.push_back(s[prev_pos.x]);
    }
    pos = prev_pos;
  }

  std::reverse(answer.begin(), answer.end());
  std::cout << answer << std::endl;
  return 0;
}

Measured memory_bytes: 211712