#include<iostream>
#include<bits/stdc++.h>
#include<vector>
#include<cmath>
#include<set>
#include<utility>
#include<algorithm>
#include<functional>
using namespace std;
typedef unsigned long long ull;
typedef pair<ull,ull> p;
#define mp make_pair
#define append push_back
vector<ull>v;
set<ull>s;
multiset<ull>ms;
ull prime[10000000];
#define f(i,a,b) for(int i=a;i<(b);i++)
#define print cout<< 
void boost() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
}

vector<ull>visited(10000000,0);
vector<ull>adj[10000];

struct node {
    ull data;
    node *left;
    node *right;
};
 
node *getNode(ull val) {
    node *newNode = new node();
    newNode->data = val;
    newNode->left = newNode->right = NULL;
    return newNode;
}
 
 
node *findNode(node *root, ull data) {
    if (root->data == data) 
        return root;
    if (root->left) findNode(root->left, data);
    if (root->right) findNode(root->right, data);
}
 
void display(node *root) {
    // displaying the tree
    queue<node*> Q;
    Q.push(root);
    while (!Q.empty()) {
        node *x = Q.front();
        Q.pop();
        if (x->left) Q.push(x->left);
        if (x->right) Q.push(x->right);
        cout << x->data << " ";
    }
    cout << endl;
}
 
node *copy(node *root) {
    if (!root) 
        return root;
    node *temp = new node();
    temp->data = root->data;
    temp->left = copy(root->left);
    temp->right = copy(root->right);
    return temp;
}
 
void mirror(node *root) {
    if (root) {
        mirror(root->left);
        mirror(root->right);
        node *temp = root->left;
        root->left = root->right;
        root->right = temp;
    }
    return;
}
 
int findMirror(int target, node *left, node *right) {
    if (left == NULL || right == NULL) return 0;
    if (left->data == target) return right->data;
    if (right->data == target) return left->data;
    int mirrorValue = findMirror(target, left->left, right->right);
    if (mirrorValue) return mirrorValue;
    return findMirror(target, left->right, right->left);
}

ull ncrmodp(ull num,ull r,ull mod)
{
    ull C[r+1];
    ull i,j;
    memset(C,0,sizeof(C));
    C[0]=1;
    for(i=1;i<=num;i++)
    {
        for(j=min(i,r);j>0;j--)
        {
            C[j]=((C[j])%mod+(C[j-1])%mod)%mod;
        }
    }
    return C[r];
} 

ull multiply(ull n,ull m)
{
    
    ull prod=1;
    f(i,0,n)
    {
        prod*=v[i];
        prod=prod%m;
    }
    return prod;
}

ull gcd(ull a, ull b) { return b == 0 ? a : gcd(b, a % b); }

ull power(ull x,ull y,ull p)
{
    ull res = 1;     
    x = x % p; 
 
    while (y > 0)
    {
        if (y & 1)
            res = (res*x) % p;
 
        y = y>>1; // y = y/2
        x = (x*x) % p;  
    }
    return res;
}

void dfs(int k) 
{
visited[k] = 1;
    for(int i = 0;i < adj[k].size();++i)   
    {
        if(visited[adj[k][i]] == 0)
        {
           dfs(adj[k][i]);
        }
    }
}

void sieve(ull ending)
{
    for(int i=2;i<ending;i++)
        prime[i]=1;
    for(int i=2;i*i<=ending;i++)
    {
        if(prime[i]==1)
            {
                for(int j=2*i;j<=ending;j=j+i)
                {
                    prime[j]=0;
                }
            }
    }
    prime[1]=0;
}

int main()
{
    boost();
    ull i,j;
    ull t,n;
    string a,b;
    cin>>a>>b;
    int dp[3001][3001];
    for(i=0;i<=a.length();i++)
    {
        for(j=0;j<=b.length();j++)
        {
            if(i==0 || j==0)
            dp[i][j]=0;
            else if(a[i-1]==b[j-1])
            {
                dp[i][j]=dp[i-1][j-1]+1;
            }
            else
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
    
    char ans[100000];
    ull ind=dp[a.length()][b.length()];
    i=a.length();
    j=b.length();
    while(i>0 && j>0)
    {
        if(a[i-1]==b[j-1])
        {
            ans[ind-1]=a[i-1];
            ind--;
            i--;
            j--;
        }
        else if(dp[i-1][j]>dp[i][j-1])
        i--;
        else
        j--;
    }
    cout<<ans<<endl;
return 0;
}


Measured memory_bytes: 113920