#include <bits/stdc++.h>
using namespace std;
char s1[128];
int l1;
char s2[128];
int l2;
char virus[128];
int lv;
int nxt[128][128];
vector<int> froms[128][128];
void calc_nxt() {
  char tmp[128];
  strcpy(tmp, virus);
  for (int l = 0; l < lv; l++) {
    for (char ch = 'A'; ch <= 'Z'; ch++) {
      tmp[l] = ch;
      for (int i = l + 1; i >= 0; i--) {
        if (!strncmp(tmp + l + 1 - i, virus, i)) {
          nxt[l][(int)ch] = i;
          break;
        }
      }
      froms[nxt[l][(int)ch]][(int)ch].push_back(l);
    }
    tmp[l] = virus[l];
  }
}
struct Path {
  int i, j, k;
};
bool operator<(const Path &a, const Path &b) {
  if (a.i != b.i) return a.i < b.i;
  if (a.j != b.j) return a.j < b.j;
  if (a.k != b.k) return a.k < b.k;
  return false;
}
pair<int, Path> dp[128][128][128];
pair<int, Path> takeDP(int i, int j, int k) {
  pair<int, Path> t = dp[i][j][k];
  t.second = {i, j, k};
  return t;
}
string getPath(pair<int, Path> runner) {
  string s;
  while (runner.first != 0) {
    Path p = runner.second;
    auto nr = dp[p.i][p.j][p.k];
    Path np = nr.second;
    if (np.i < p.i && np.j < p.j) {
      s += s1[p.i - 1];
    }
    runner = nr;
  }
  reverse(s.begin(), s.end());
  if (s == "") return "0";
  return s;
}
bool isSub(string s, string p) {
  size_t l = 0;
  for (auto ch : p) {
    cout << ch;
    while (l < s.size() && s[l] != ch) {
      l++;
    }
    if (l == s.size()) {
      cout << endl;
      return false;
    }
    l++;
  }
  cout << endl;
  return true;
}
int TestNum;
int main() {
  scanf("%s%s%s", s1, s2, virus);
  l1 = strlen(s1);
  l2 = strlen(s2);
  lv = strlen(virus);
  calc_nxt();
  for (int i = 0; i < l1; i++) {
    for (int k = 1; k <= lv; k++) {
      dp[i][0][k].first = -0x1f1f1f1f;
    }
  }
  for (int i = 0; i < l2; i++) {
    for (int k = 1; k <= lv; k++) {
      dp[0][i][k].first = -0x1f1f1f1f;
    }
  }
  dp[0][0][0].first = 0;
  for (int i = 0; i < l1; i++) {
    for (int j = 0; j < l2; j++) {
      for (int k = 0; k < lv; k++) {
        auto &to = dp[i + 1][j + 1][k];
        auto from1 = takeDP(i + 1, j, k), from2 = takeDP(i, j + 1, k);
        to = max(from1, from2);
        if (s1[i] == s2[j]) {
          for (auto tk : froms[k][(int)s1[i]]) {
            auto from = takeDP(i, j, tk);
            from.first += 1;
            to = max(to, from);
          }
        }
      }
    }
  }
  auto best = dp[0][0][0];
  for (int k = 0; k < lv; k++) {
    best = max(best, takeDP(l1, l2, k));
  }
  string s = getPath(best);
  cout << s << endl;
}
