#include <algorithm>
#include <bits/stdc++.h>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

// lib/util.hpp
#ifndef UTIL_HPP
#define UTIL_HPP


typedef std::int_fast64_t i64;
typedef std::uint_fast64_t u64;
typedef std::int_fast32_t i32;
typedef std::uint_fast32_t u32;

namespace tools {
  template <typename T>
  void read(std::vector<T>& vector, const typename std::vector<T>::size_type size) {
    vector.reserve(size);
    std::copy_n(std::istream_iterator<T>(std::cin), size, std::back_inserter(vector));
  }

  template <typename T, std::size_t N>
  void read(std::array<T, N>& array) {
    std::copy_n(std::istream_iterator<T>(std::cin), N, array.begin());
  }
}

#endif

// lib/persistent_stack.hpp
#ifndef PERSISTENT_STACK_HPP
#define PERSISTENT_STACK_HPP


/*
usage:

tools::persistent_stack<std::int_fast64_t> stack;
stack = stack.push(42);
stack = stack.pop();
*/

namespace tools {
  template <typename T>
  class persistent_stack {
  private:
    class node {
    public:
      std::shared_ptr<node> next;
      T value;
      node(const std::shared_ptr<node>& next, const T& value) :
        next(next), value(value) {
      }
    };

    std::shared_ptr<node> m_root;
    std::size_t m_size;

    persistent_stack(const std::shared_ptr<node>& root, const std::size_t size) :
      m_root(root), m_size(size) {
    }

  public:
    class iterator {
      friend class persistent_stack<T>;

    private:
      std::shared_ptr<node> ptr;

      iterator(const std::shared_ptr<node>& ptr) :
        ptr(ptr) {
      }

    public:
      bool operator==(const iterator& other) const {
        return this->ptr == other.ptr;
      }
      bool operator!=(const iterator& other) const {
        return !(*this == other);
      }
      T operator*() const {
        return this->ptr->value;
      }
      iterator& operator++() {
        this->ptr = this->ptr->next;
        return *this;
      }
      using difference_type = std::ptrdiff_t;
      using value_type = T;
      using pointer = T*;
      using reference = T&;
      using iterator_category = std::input_iterator_tag;
    };

    persistent_stack() :
      m_root(), m_size(0) {
    }

    const T& top() const {
      return this->m_root->value;
    }

    bool empty() const {
      return this->m_size == 0;
    }

    std::size_t size() const {
      return this->m_size;
    }

    persistent_stack<T> push(const T& x) const {
      return persistent_stack<T>(std::make_shared<node>(this->m_root, x), this->m_size + 1);
    }

    template <class... Args>
    persistent_stack<T> emplace(Args&&... args) const {
      return persistent_stack<T>(std::make_shared<node>(this->m_root, T(std::forward<Args>(args)...)), this->m_size + 1);
    }

    persistent_stack<T> pop() const {
      return persistent_stack<T>(this->m_root->next, this->m_size - 1);
    }

    iterator begin() const {
      return iterator(this->m_root);
    }

    iterator end() const {
      return iterator(std::shared_ptr<node>());
    }

    bool operator==(const persistent_stack<T>& other) const {
      if (this->m_size != other.m_size) return false;
      for (auto it1 = this->begin(), it2 = other.begin(); it1 != this->end() && it2 != other.end(); ++it1, ++it2) {
        if (*it1 != *it2) return false;
      }
      return true;
    }
    bool operator!=(const persistent_stack<T>& other) const {
      return !(*this == other);
    }
    bool operator<(const persistent_stack<T>& other) const {
      if (this->m_size < other.m_size) return true;
      for (auto it1 = this->begin(), it2 = other.begin(); it1 != this->end() && it2 != other.end(); ++it1, ++it2) {
        if (*it1 < *it2) return true;
        if (*it1 > *it2) return false;
      }
      return false;
    }

    explicit operator std::vector<T>() const {
      std::vector<T> vector;
      vector.reserve(this->m_size);
      std::copy(this->begin(), this->end(), std::back_inserter(vector));
      std::reverse(vector.begin(), vector.end());
      return vector;
    }

    template <typename U = T, typename std::enable_if<std::is_same<U, char>::value, std::nullptr_t>::type = nullptr>
    explicit operator std::string() const {
      const std::vector<char> vector = static_cast<std::vector<char>>(*this);
      return std::string(vector.begin(), vector.end());
    }

    using value_type = T;
    using size_type = std::size_t;
    using reference = T&;
    using const_reference = const T&;
  };
}

#endif

// main.cpp

int main() {
  std::string s;
  std::string t;
  std::cin >> s >> t;
  const i64 M = s.size();
  const i64 N = t.size();

  constexpr i64 INF = std::numeric_limits<i64>::max();
  std::string i2c = "abcdefghijklmnopqrstuvwxyz";
  std::unordered_map<char, i64> c2i;
  for (i64 i = 0; i < 26; ++i) {
    c2i.insert(std::make_pair(i2c[i], i));
  }

  std::vector<std::vector<i64>> s_next(M + 1, std::vector<i64>(26, INF));
  for (i64 i = M; i >= 0; --i) {
    if (i < M) {
      for (i64 j = 0; j < 26; ++j) {
        if (s_next[i][j] == INF) s_next[i][j] = s_next[i + 1][j];
      }
    }
    if (i > 0) {
      s_next[i - 1][c2i[s[i - 1]]] = i - 1;
    }
  }
  std::vector<std::vector<i64>> t_next(N + 1, std::vector<i64>(26, INF));
  for (i64 i = N; i >= 0; --i) {
    if (i < N) {
      for (i64 j = 0; j < 26; ++j) {
        if (t_next[i][j] == INF) t_next[i][j] = t_next[i + 1][j];
      }
    }
    if (i > 0) {
      t_next[i - 1][c2i[t[i - 1]]] = i - 1;
    }
  }

  // dp[i][j] ... sを左からi文字、tを左からj文字見た時点での最長文字列
  std::vector<std::vector<tools::persistent_stack<char>>> dp(M + 1, std::vector<tools::persistent_stack<char>>(N + 1));
  std::vector<std::vector<bool>> valid(M + 1, std::vector<bool>(N + 1, false));
  valid[0][0] = true;
  const auto update_dp = [&](const i64 i, const i64 j) {
    if (valid[i][j]) {
      for (i64 k = 0; k < 26; ++k) {
        if (s_next[i][k] != INF && t_next[j][k] != INF) {
          if (valid[s_next[i][k] + 1][t_next[j][k] + 1]) {
            if (dp[i][j].size() + 1 > dp[s_next[i][k] + 1][t_next[j][k] + 1].size()) dp[s_next[i][k] + 1][t_next[j][k] + 1] = dp[i][j].push(i2c[k]);
          } else {
            valid[s_next[i][k] + 1][t_next[j][k] + 1] = true;
            dp[s_next[i][k] + 1][t_next[j][k] + 1] = dp[i][j].push(i2c[k]);
          }
        }
      }
    }
  };
  for (i64 i = 0; i <= std::min(M, N); ++i) {
    update_dp(i, i);
    for (i64 j = i + 1; j <= M; ++j) {
      update_dp(j, i);
    }
    for (i64 j = i + 1; j <= N; ++j) {
      update_dp(i, j);
    }
  }

  tools::persistent_stack<char> answer;
  for (i64 i = 0; i <= M; ++i) {
    for (i64 j = 0; j <= N; ++j) {
      if (dp[i][j].size() > answer.size()) answer = dp[i][j];
    }
  }
  std::cout << static_cast<std::string>(answer) << std::endl;

  return 0;
}

Measured memory_bytes: 315776