#include<bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <functional> // for less
#include <iostream>
using namespace __gnu_pbds;
void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i : x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define dbg(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define  dbg(x...)
#endif
#define EACH(x, a) for (auto& x: a)
template<class A> void read(vector<A>& v);
template<class A, size_t S> void read(array<A, S>& a);
template<class T> void read(T& x) {
    cin >> x;
}
void read(double& d) {
    string t;
    read(t);
    d = stod(t);
}
void read(long double& d) {
    string t;
    read(t);
    d = stold(t);
}
template<class H, class... T> void read(H& h, T&... t) {
    read(h);
    read(t...);
}
template<class A> void read(vector<A>& x) {
    EACH(a, x)
    read(a);
}
template<class A, size_t S> void read(array<A, S>& x) {
    EACH(a, x)
    read(a);
}
template<typename T1, typename T2>istream& operator>>(istream& in, pair<T1, T2> &a) {in >> a.first >> a.second; return in;}
template<typename T1, typename T2>ostream& operator<<(ostream& out, pair<T1, T2> a) {out << a.first << " " << a.second; return out;}
template<typename T, typename T1>T amax(T &a, T1 b) {if (b > a)a = b; return a;}
template<typename T, typename T1>T amin(T &a, T1 b) {if (b < a)a = b; return a;}
#define sc(n)                        scanf("%d",&n)
#define scc(n)                       scanf("%c",&n)
#define sl(n)                       scanf("%lld",&n)
#define sf(n)                       scanf("%lf",&n)
#define ll long long
#define vl vector<ll>
#define pb                push_back
#define ppb               pop_back
#define pf                push_front
#define mp make_pair
#define ppf               pop_front#define mp make_pair
#define f(i, l, r) for(ll i = int(l); i < int(r); i++)
#define fr(i, l, r) for(ll i = int(l); i >= int(r); i--)
#define fi first
#define se second
#define rsz resize
#define cnl cout << "\n"
#define all(x) x.begin(), x.end()
#define allr(x) x.rbegin(), x.rend()
#define sz(x) ((int)x.size())
#define ln(x) ((int)x.length())
#define setbits(x)  __builtin_popcountll(x)
#define clr(x,v) memset(x, v, sizeof(x))
#define endl "\n"
#define rt return
#define ins insert
#define fast ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
typedef pair<ll, ll> pll;
#define uml unordered_map<ll,ll>
#define vpl vector <pll >
typedef tree<ll, null_type, less_equal<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
#define ld long double
#define vt vector
const int MAXN = 1e6 + 500000;
ll mod = 1e9 + 7;
ll dx[] = {0, -1, 1, 0, -1, -1, 1, 1};
ll dy[] = {1, 0, 0, -1, 1, -1, -1, 1};
string a, b, c;
vl lps;
ll dp[103][103][103];
ll go(ll i, ll j, ll match) {
    if (match == ln(c)) return INT_MIN;
    if (i == ln(a) || j == ln(b)) {
        return 0;
    }
    if (dp[i][j][match] != -1)return dp[i][j][match];
    ll ans = 0;
    if (a[i] == b[j]) {
        ll cc = match;
        while (cc > 0 && a[i] != c[cc]) cc = lps[cc - 1];
        if (a[i] == c[cc]) cc++;
        ans = max(ans, 1 + go(i + 1, j + 1, cc));
    }
    ans = max(ans, go(i + 1, j, match));
    ans = max(ans, go(i, j + 1, match));
    return dp[i][j][match] = ans;
}

void solve() {
    cin >> a >> b >> c;
    lps.assign(ln(c) + 1, 0);
    ll j = 0;
    f(i, 1, ln(c)) {
        while (j > 0 && c[i] != c[j]) j = lps[j - 1];
        if (c[i] == c[j]) j++;
        lps[i] = j;
    }
    clr(dp, -1);
    ll ans = go(0, 0, 0);
    string s = "";
    ll match = 0;
    ll i = 0; j = 0;
    while (i < ln(a) && j < ln(b) && match != ln(c)) {
        if (a[i] == b[j]) {
            ll cc = match;
            while (cc > 0 && a[i] != c[cc]) cc = lps[cc - 1];
            if (a[i] == c[cc]) cc++;
            if (ans == 1 + go(i + 1, j + 1, cc)) {
                s += a[i];
                ans -= 1;
                match = cc;
                i++, j++;
                continue;
            }
        }
        if (ans == go(i + 1, j, match)) i++;
        else if (ans == go(i, j + 1, match)) j++;
    }
    assert(ans == 0);
    if (ln(s) == 0) {
        cout << 0 << endl;
        rt;
    }
    cout << s << endl;
}

signed main() {
// #ifndef ONLINE_JUDGE
//     freopen("input.txt", "r", stdin);
//     freopen("output.txt", "w", stdout);
// #endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    int T = 1;
    // cin >> T;
    while (T--) {
        solve();
    }
}