#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;   }   