import std.stdio, std.conv, std.string, std.bigint;
import std.math, std.random, std.datetime;
import std.array, std.range, std.algorithm, std.container, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

/*

部分文字列　文字列の一致

sのi文字目までとtのj文字目まででやった場合の答えをxs[i][j]とする

s[i]とt[j]が一致する場合、
	xs[i][j] = xs[i - 1][j - 1] + 1
そうでない場合、
	xs[i][j] = max(xs[i - 1][j], xs[i][j - 1]))

ただし添字が負になる項は 0

求めるものはxs[n][m]である

上記を求めたあと、文字列は以下のようにして作る

string solve(int i, int j){
	if(s[i] == t[j]){
		if(i == 0 || j == 0) return "" ~ s[i];
		else return solve(i - 1, j - 1) ~ s[i];
	}
	else{
		if(i == 0 && j == 0) return "";
		if(i == 0) return solve(i, j - 1);
		if(j == 0) return solve(i - 1, j);
		if(xs[i - 1][j] > xs[i][j - 1]) return solve(i - 1, j);
		else return solve(i, j - 1);
	}
}



// メモ化再帰のほうがよかったかも

*/

void main(){
	string s = readln.chomp;
	string t = readln.chomp;
	
	long n = s.length;
	long m = t.length;
	
	int[][] xs;
	
	foreach(i; 0 .. n){
		xs ~= new int[](m);
		foreach(j; 0 .. m){
			debug writeln("i:", i, " j: ", j, " xs:", xs);
			if(s[i] == t[j]){
				if(i == 0 || j == 0) xs[i][j] = 1;
				else xs[i][j] = xs[i - 1][j - 1] + 1;
			}
			else{
				if(i == 0 && j == 0) xs[i][j] = 0;
				else if(i == 0) xs[i][j] = xs[i][j - 1];
				else if(j == 0) xs[i][j] = xs[i - 1][j];
				else xs[i][j] = max(xs[i - 1][j], xs[i][j - 1]);
			}
		}
	}
	
	string solve(long i, long j){
		if(s[i] == t[j]){
			if(i == 0 || j == 0) return "" ~ s[i];
			else return solve(i - 1, j - 1) ~ s[i];
		}
		else{
			if(i == 0 && j == 0) return "";
			if(i == 0) return solve(i, j - 1);
			if(j == 0) return solve(i - 1, j);
			if(xs[i - 1][j] > xs[i][j - 1]) return solve(i - 1, j);
			else return solve(i, j - 1);
		}
	}
	solve(n - 1, m - 1).writeln;
}
