//         PAR_YUMMM            //
                                           //           CPP                //
#include <bits/stdc++.h>
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;

#define ll long long
#define ld long double
ll const N=1e5+5;

#define pb push_back
#define popb pop_back()
#define pf push_front
#define popf pop_front()
#define si size()
#define be begin()
#define en end()
#define all(v) v.be, v.en
#define le length()
#define mp make_pair
#define mt make_tuple
#define acc(v) accumulate(all(v), 0)
#define F first
#define S second
 
#define forz(i, n) for (ll i = 0; i < n; i++)
#define fore(i, m, n) for (ll i = m; i <= n; i++)
#define rforz(i, n) for (ll i = n - 1; i >= 0; i--)
#define rfore(i, m, n) for (ll i = n; i >= m; i--)
#define deci(n) fixed << setprecision(n)
#define high(n) __builtin_popcount(n)
#define highll(n) __builtin_popcountll(n)
#define parity(n) __builtin_parity(n)
#define ctz(n) __builtin_ctz(n)
#define lb lower_bound
#define ub upper_bound
#define er equal_range
#define maxe *max_element
#define mine *min_element
#define mod 1000000007
#define mod2 998244353
#define gcd __gcd
#define sexy ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
 
#define endl "\n"
#define p0(a) cout << a << " "
#define p1(a) cout << a << endl
#define p2(a, b) cout << a << " " << b << endl
#define p3(a, b, c) cout << a << " " << b << " " << c << endl
#define p4(a, b, c, d) cout << a << " " << b << " " << c << " " << d << endl
 
#define oset tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
#define osetll tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update>
//member functions :
//1. order_of_key(k) : number of elements strictly lesser than k
//2. find_by_order(k) : k-th element in the set
#define ofk order_of_key
#define fbo find_by_order

ll po(ll x,ll y,ll m){
    if(y==0){
        return 1;
    }
    ll temp=po(x,y/2,m);
    if(y%2==0){
        return ((temp%m)*(temp%m))%m;
    }else{
        return (((x%m)*(temp%m))%m*(temp)%m)%m;
    }
}

ll modi(ll a,ll m){
    return po(a,m-2,m);
}

ll lcm(ll a, ll b){ 
    return (a*b)/(gcd(a, b));
}
ll max(ll a, ll b){
  if (a > b)
    return a;
  return b;
}
ll min(ll a, ll b){
  if (a < b)
    return a;
  return b;
}

ll bins(ll ar[],ll l,ll r,ll x) 
{ 
    if (r >= l) { 
        ll mid =l+((r-l)/2); 
        if(ar[mid]==x) 
            return mid; 
        if(ar[mid]>x) 
            return bins(ar,l,mid-1,x);
        return bins(ar,mid+1,r,x); 
    } 
    return -1; 
} 

/*
SEGMENT TREE
ll n, t[4*N];
void build(ll a[], ll v, ll tl, ll tr) {
    if(tl==tr){
        t[v]=a[tl];
    }else{
        ll tm=(tl+tr)/2;
        build(a,v*2,tl,tm);
        build(a,v*2+1,tm+1,tr);
        t[v]=t[v*2]+t[v*2+1];
    }
}

ll sum(ll v, ll tl, ll tr, ll l, ll r) {
    if(l>r){ 
        return 0;
    }
    if(l==tl&&r==tr){
        return t[v];
    }
    ll tm=(tl+tr)/2;
    return sum(v*2,tl,tm,l,min(r,tm))+sum(v*2+1,tm+1,tr,max(l,tm+1),r);
}

void update(ll v, ll tl, ll tr, ll pos, ll new_val){
    if(tl==tr){
        t[v]=new_val;
    }else{
        ll tm=(tl+tr)/2;
        if(pos<=tm)
            update(v*2,tl,tm,pos,new_val);
        else
            update(v*2+1,tm+1,tr,pos,new_val);
        t[v]=t[v*2]+t[v*2+1];
    }
}
*/

/*
DSU

ll parent[N];
ll size[N];
set <ll> st;
void make(ll v) {
    parent[v] = v;
    size[v] = 1;
    st.insert(v);
}

ll findset(ll v) {
    if (v == parent[v])
        return v;
    return parent[v] = findset(parent[v]);
}

void merge(ll a, ll b){
    a = findset(a);
    b = findset(b);
    if (a != b) {
        if (size[a] < size[b])
            swap(a, b);
        parent[b] = a;
        size[a] += size[b];
    }
}

void merge2(ll x,ll y){
    auto it=st.ub(x);
    while(it!=st.end()&&*it<=y)
    {
        merge(x,*it);
        ll value=*it;
        st.erase(it);
        it=st.ub(value);
    }
}
*/

/*
BFS
vector<vector<ll>> adj;
ll n; // number of nodes
ll s; // source vertex

queue<ll> q;
vector<bool> used(n);
vector<ll> d(n), p(n);

q.push(s);
used[s] = true;
p[s] = -1;
while (!q.empty()) {
    ll v = q.front();
    q.pop();
    for (ll u : adj[v]) {
        if (!used[u]) {
            used[u] = true;
            q.push(u);
            d[u] = d[v] + 1;
            p[u] = v;
        }
    }
}
*/

/*
DFS
vector<vector<ll>> adj; // graph represented as an adjacency list
ll n; // number of vertices

vector<bool> visited;

void dfs(ll v) {
    visited[v] = true;
    for (ll u : adj[v]) {
        if (!visited[u])
            dfs(u);
    }
}
*/

string lcs(string a,string b,ll x,ll y){
    ll ar[x+1][y+1];
    fore(i,0,x){
        fore(j,0,y){
            if(i==0||j==0){
                ar[i][j]=0;
            }else if(a[i-1]==b[j-1]){
                ar[i][j]=ar[i-1][j-1]+1;
            }else{
                ar[i][j]=max(ar[i-1][j],ar[i][j-1]);
            }
        }
    }
    string s="";
    while(x>0&&y>0){
        if(a[x-1]==b[y-1]){
            s=a[x-1]+s;
            x--;
            y--;
        }else{
            if(ar[x-1][y]>ar[x][y-1]){
                x--;
            }else{
                y--;
            }
        }
    }
    return s;
}

int main(){
    sexy;
    ll x,y,z,p,q,r;
    string a,b;
    cin>>a;
    cin>>b;
    x=a.length();
    y=b.length();
    cout<<lcs(a,b,x,y)<<endl;
    return 0;
}


Measured memory_bytes: 70656