// Standard Stuff
#include <bits/stdc++.h>
using namespace std;

// Macros
#define F      first
#define S      second
#define PB     push_back
#define MP     make_pair
#define ALL(c) c.begin(),c.end()

// Rename Datatypes
using ll  = long long;
using ld  = long double;
using pii = std::pair <int,int>;

// Random
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
/* [a,b] */ template<class T> T rnd_IntType(T a, T b){ return uniform_int_distribution<T>(a, b)(rng); }
/* [a,b) */ template<class T> T rnd_RealType(T a, T b){ return uniform_real_distribution<T>(a,b)(rng); }

// Common Functions
ll fastpow(ll a, ll ex){ ll res = 1; while(ex){ if(ex & 1) res *= a; a *= a; ex >>= 1; } return res; }
ll fastpow(ll a, ll ex, ll m){ a %= m; ll res = 1; while(ex){ if(ex & 1) res = (a*res) % m; a = (a*a) % m; ex >>= 1; } return res; }
ll modinverse(ll a, ll m){ ll m0 = m; ll y = 0, x = 1; while (a > 1){ ll q = a / m; a %= m; swap(a,m); x -= q*y; swap(x,y); } if(x < 0) x += m0; return x; }

// Output, Common Containers
template <typename T> ostream& operator << (ostream &os, const set<T> &v) { for (T i : v) os << i << ' '; return os; }
template <typename T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ' '; return os; }
template <typename T> ostream& operator << (ostream &os, const deque<T> &v) { for (T i : v) os << i << ' '; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const pair<T, S> &v) { os << "(" << v.F << "=>" << v.S << ") "; return os; }
template <typename T, typename S> ostream& operator << (ostream &os, const map<T, S> &v) { for (auto i : v) os << i << ' '; return os; }

// Debugging
#ifdef LOCAL
	#define trace(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); d__f(_it, args); }
	void d__f(istream_iterator<string> it) {}
	template<typename Head, typename... Tail> void d__f(istream_iterator<string> it, Head H, Tail... T) { cerr << *it << " <=> [" << H << "]\n"; d__f(++it, T...); }
#else
	#define trace(args...)
#endif


// CODE STARTS HERE

const int modulo1 = 1e9+7;
const int modulo2 = 998244353;

const int mod = 1e9+7;

ll add(ll a, ll b) { return (a + b) % mod; }
ll sub(ll a, ll b) { return (a - b) % mod; }
ll mul(ll a, ll b) { return (a * b) % mod; }

signed main() {
	std::ios::sync_with_stdio(false); //Warning: Do NOT use C I/O now.
	std::cin.tie(nullptr); //Note: Comment out this line for interactive questions.
	// std::cout.setf(std::ios::fixed); std::cout.precision(20); //Note: To output decimals correctly.

	// int t; cin>>t;
	// for(int test_no = 1; test_no <= t; ++test_no){}

	string s,t;
	cin>>s>>t;

	vector<vector<int>> dp(s.size()+1, vector<int>(t.size()+1));

	for(int i=0; i<=s.size(); ++i) dp[i][0] = 0;
	for(int i=0; i<=t.size(); ++i) dp[0][i] = 0;

	for(int i=1; i<=s.size(); ++i)
		for(int j=1; j<=t.size(); ++j)
			dp[i][j] = max ({ dp[i-1][j], dp[i][j-1], dp[i-1][j-1] + ((s[i-1]==t[j-1]) ? 1 : 0) });

	// trace(dp[s.size()][t.size()].F);

	string ans = "";
	pii ptr = {s.size(), t.size()};
	while(ptr.F * ptr.S != 0){
		int c = (s[ptr.F-1]==t[ptr.S-1]) ? 1 : 0;
		if(dp[ptr.F][ptr.S] == dp[ptr.F-1][ptr.S-1] + c){
			if(c) ans = s[ptr.F-1] + ans;
			ptr = {ptr.F-1, ptr.S-1};
		}
		else if (dp[ptr.F][ptr.S] == dp[ptr.F-1][ptr.S])
			ptr = {ptr.F-1, ptr.S};
		else
			ptr = {ptr.F, ptr.S-1};
	}

	cout<<ans;
}

Measured memory_bytes: 35584