Problem:
共通部分文字列
問題
2 個の文字列が与えられたとき, 両方の文字列に含まれる文字列のうち最も長いものを探し, その長さを答えるプログラムを作成せよ.
ここで, 文字列 s が文字列 t に含まれるとは, t の中に s が連続して現れることをいう. 空文字列, すなわち長さ 0 の文字列は, どんな文字列にも含まれる. 例えば, 文字列 ABRACADABRA には次の文字列が含まれる: ABRA, RAC, D, ACADABRA, ABRACADABRA,空文字列など. 一方, 文字列 ABRACADABRA には次の文字列は含まれない: ABRC, RAA,BA, K など.
例
例 1: 文字列として ABRACADABRA と ECADADABRBCRDARA が与えられた場合, 両方に含まれる文字列には CA や CADA や ADABR や空文字列などがある. そのうち最も長いのは ADABR であり, その長さは 5 である. 2 個の文字列の中に含まれる ADABR
の位置を以下に示す.
ABRAC
ADABR
A
ECAD
ADABR
BCRDARA
例 2: 文字列として
UPWJCIRUCAXIIRGL
と
SBQNYBSBZDFNEV
が与えられた場合, 両方に含まれる文字列は空文字列のみであり, その長さは 0 である.
入力
入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．
入力は 2 行からなり, 1 行目に 1 個目の文字列が, 2 行目に 2 個目の文字列が与えられる. 文字列は英大文字からなり, 各々の文字列の長さは 1 以上 4000 以下である.
採点用データのうち, 配点の 30% 分については, 各々の文字列の長さは 1 以上 50以下である.
入力の終わりは EOF で示される. データセットの数は 10 を超えない．
出力
データセットごとに与えられた 2 個の文字列の両方に含まれる文字列のうち最も長いものの長さを 1 行に出力する.
入出力例
入力例
ABRACADABRA
ECADADABRBCRDARA
UPWJCIRUCAXIIRGL
SBQNYBSBZDFNEV
出力例
5
0
上記問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
string S, T, U;
int solve(string U1, string U2) {
	int t = 0, maxn = 0;
	for (int i = 0; i < min(U1.size(), U2.size()); i++) {
		if (U1[i] == U2[i])t++;
		else { maxn = max(t, maxn); t = 0; }
	}
	return max(t, maxn);
}
int main() {
	while (cin >> S) {
		cin >> T; int ret = 0; U = "";
		for (int i = 0; i <= T.size(); i++)ret = max(ret, solve(S, T.substr(i, T.size() - i)));
		for (int i = 0; i <= S.size(); i++) { ret = max(ret, solve(S, U + T)); U += "-"; }
		cout << ret << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3312
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    string S1, S2;

    while (getline(cin, S1) && getline(cin, S2)) {
        int n = S1.length();
        int m = S2.length();

        vector<int> prev(m + 1, 0), curr(m + 1, 0);
        int ans = 0;

        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (S1[i - 1] == S2[j - 1]) {
                    curr[j] = prev[j - 1] + 1;
                    ans = max(ans, curr[j]);
                } else {
                    curr[j] = 0;
                }
            }
            swap(prev, curr);
        }

        cout << ans << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3384
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string s, t;
    // 複数データセット、EOFまでループ
    while (true) {
        if (!getline(cin, s)) break;  // 1行目が読めなければ終了
        if (!getline(cin, t)) break;  // 対応する2行目を読めなければ終了

        int n = s.size();
        int m = t.size();
        // DPの各行を保持する配列。メモリをO(m)に抑える。
        vector<int> prev(m + 1, 0), curr(m + 1, 0);

        int best = 0;  // 最長共通部分文字列の長さ

        // i文字目を末尾とするsの部分文字列と、
        // j文字目を末尾とするtの部分文字列の一致長を計算
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (s[i - 1] == t[j - 1]) {
                    // 末尾文字が一致する場合、ひとつ前の状態から延長
                    curr[j] = prev[j - 1] + 1;
                    best = max(best, curr[j]);
                } else {
                    // 一致しなければ長さ0にリセット
                    curr[j] = 0;
                }
            }
            // 次の行計算のためprevとcurrを入れ替え
            swap(prev, curr);
            // currは0で埋め直しておく（安全策）
            fill(curr.begin(), curr.end(), 0);
        }

        // 結果出力
        cout << best << "\n";
    }

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3712
final_rank: 1

code_snippet: #include "bits/stdc++.h"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
using namespace __gnu_pbds;
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define rep(i, m, n) for (ll i = (ll)m; i < (ll)n; i++)
#define drep(i, m, n) for (ll i = m - 1; i >= n; i--)
#define Endl endl
#define all(a) a.begin(), a.end()
#define pr(i, j) make_pair(i, j)
#define isin(x, l, r) (l <= x && x < r)
#define chmin(a, b) a = min(a, b)
#define chmax(a, b) a = max(a, b)
#define srt(ar) sort(ar.begin(), ar.end())
#define rev(ar) reverse(ar.begin(), ar.end())
#define jge(f, s, t) cout << (f ? s : t) << endl
template <typename T>
using ordered_set = tree<T, null_type, std::less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#define printar(ar)             \
    do                          \
    {                           \
        for (auto dbg : ar)     \
        {                       \
            cout << dbg << " "; \
        }                       \
        cout << endl;           \
    } while (0)
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
template <class T, ll n, ll idx = 0>
auto make_vec(const ll (&d)[n], const T &init) noexcept
{
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, ll n>
auto make_vec(const ll (&d)[n]) noexcept
{
    return make_vec(d, T{});
}
//////////////// 以下を貼る ////////////////
template <class T>
size_t HashCombine(const size_t seed, const T &v)
{
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
/* pair用 */
template <class T, class S>
struct std::hash<std::pair<T, S>>
{
    size_t operator()(const std::pair<T, S> &keyval) const noexcept
    {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
/* vector用 */
template <class T>
struct std::hash<std::vector<T>>
{
    size_t operator()(const std::vector<T> &keyval) const noexcept
    {
        size_t s = 0;
        for (auto &&v : keyval)
            s = HashCombine(s, v);
        return s;
    }
};
/* tuple用 */
template <int N>
struct HashTupleCore
{
    template <class Tuple>
    size_t operator()(const Tuple &keyval) const noexcept
    {
        size_t s = HashTupleCore<N - 1>()(keyval);
        return HashCombine(s, std::get<N - 1>(keyval));
    }
};
template <>
struct HashTupleCore<0>
{
    template <class Tuple>
    size_t operator()(const Tuple &keyval) const noexcept { return 0; }
};
template <class... Args>
struct std::hash<std::tuple<Args...>>
{
    size_t operator()(const tuple<Args...> &keyval) const noexcept
    {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};
////////////////////////////////////////////
/////////////////////////////////////////////////////////////////

const ull mod = 0x1fffffffffffffff, base = chrono::duration_cast<chrono::microseconds>(chrono::system_clock::now().time_since_epoch()).count() % mod;
struct RollingHash
{
    vector<ull> hashed, power;

    static constexpr ull mask(ll a) { return (1ULL << a) - 1; }

    inline ull mul(ull a, ull b) const
    {
        // without __uint128_t
        ull a31 = a >> 31, b31 = b >> 31;
        a &= mask(31);
        b &= mask(31);
        ull x = a * b31 + b * a31;
        ull ans = (a31 * b31 << 1) + (x >> 30) + ((x & mask(30)) << 31) + a * b;
        //*/
        ans = (ans >> 61) + (ans & mod);
        if (ans >= mod)
            ans -= mod;
        return ans;
    }

    RollingHash(const string &s)
    {
        ll n = s.size();
        hashed.assign(n + 1, 0);
        power.assign(n + 1, 0);
        power[0] = 1;
        for (ll i = 0; i < n; i++)
        {
            power[i + 1] = mul(power[i], base);
            hashed[i + 1] = mul(hashed[i], base) + s[i];
            if (hashed[i + 1] >= mod)
                hashed[i + 1] -= mod;
        }
    }

    ull get(ll l, ll r) const
    {
        ull ret = hashed[r] + mod - mul(hashed[l], power[r - l]);
        if (ret >= mod)
            ret -= mod;
        return ret;
    }

    ull connect(ull h1, ull h2, ll h2len) const
    {
        ull ret = mul(h1, power[h2len]) + h2;
        if (ret >= mod)
            ret -= mod;
        return ret;
    }

    void connect(const string &s)
    {
        ll n = hashed.size() - 1, m = s.size();
        hashed.resize(n + m + 1);
        power.resize(n + m + 1);
        for (ll i = n; i < n + m; i++)
        {
            power[i + 1] = mul(power[i], base);
            hashed[i + 1] = mul(hashed[i], base) + s[i - n];
            if (hashed[i + 1] >= mod)
                hashed[i + 1] -= mod;
        }
    }

    ll LCP(const RollingHash &b, ll l1, ll r1, ll l2, ll r2)
    {
        ll len = min(r1 - l1, r2 - l2);
        ll low = -1, high = len + 1;
        while (high - low > 1)
        {
            ll mid = (low + high) / 2;
            if (get(l1, l1 + mid) == b.get(l2, l2 + mid))
                low = mid;
            else
                high = mid;
        }
        return low;
    }
};

/*

mod 2^61 - 1 の RollingHash です  結構強いです
名前の衝突がある場合は namespace で囲うと良いです
hashed[i] : s[0, i) のハッシュ結果  hashed[i + 1] = s[i] + s[i-1] * power[1] + s[i-2] * power[2] + ...
power[i] : base ** i
get(l, r) : s[l, r) のハッシュ結果  s[r-1] + s[r-2] * power[1] + ... + s[l] * power[r - l + 1]
connect(h1, h2, h2len) : 2つのハッシュ結果からそれらを繋げたときのハッシュ結果を得ます
connect(s) : コンストラクタで渡した文字列に s を繋げたことにします  過去必要になったやつ
LCP(...) : Longest Common Prefix の長さ

*/
////////////////////////////////////////
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    string s, t;
    while (cin >> s >> t)
    {
        vector<vector<ll>> dp(s.length() + 1, vector<ll>(t.length() + 1));
        rep(i, 0, s.length())
        {
            rep(j, 0, t.length())
            {
                if (s[i] == t[j])
                {
                    chmax(dp[i + 1][j + 1], dp[i][j] + 1);
                }
            }
        }
        ll ans = 0;
        rep(i, 0, s.length() + 1)
        {
            rep(j, 0, t.length() + 1)
            {
                chmax(ans, dp[i][j]);
            }
        }
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 340
memory_kb: 128768
final_rank: 20

code_snippet: #line 1 "aizu-suffix-array.test.cpp"
#define PROBLEM "https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0528"

#line 1 "/Users/alfred/Desktop/Tools/cpp-templates/src/alfred/config/io-sync-off.hpp"
#include <bits/stdc++.h>

inline void optimizeIO(void) {
    std::ios::sync_with_stdio(false);
    std::cin.tie(NULL), std::cout.tie(NULL);
}
#line 1 "/Users/alfred/Desktop/Tools/cpp-templates/src/alfred/string/suffix-array.hpp"



#line 7 "/Users/alfred/Desktop/Tools/cpp-templates/src/alfred/string/suffix-array.hpp"

#line 1 "/Users/alfred/Desktop/Tools/cpp-templates/src/alfred/data_structure/sparse-table.hpp"



#line 7 "/Users/alfred/Desktop/Tools/cpp-templates/src/alfred/data_structure/sparse-table.hpp"

template <class T>
struct MaxInfo {
    T val;
    MaxInfo(void) { val = std::numeric_limits<T>::min(); }
    template <class InitT>
    MaxInfo(InitT x) { val = x; }
    MaxInfo operator+(MaxInfo &x) {
        return {std::max(val, x.val)};
    }
};
template <class T>
struct MinInfo {
    T val;
    MinInfo(void) { val = std::numeric_limits<T>::max(); }
    template <class InitT>
    MinInfo(InitT x) { val = x; }
    MinInfo operator+(MinInfo &x) {
        return {std::min(val, x.val)};
    }
};
template <class T>
struct GcdInfo {
    T val;
    GcdInfo(void) { val = T(); }
    template <class InitT>
    GcdInfo(InitT x) { val = x; }
    GcdInfo operator+(GcdInfo &x) {
#if __cplusplus >= 201703L
        return {std::gcd(x.val, val)};
#else
        return {__gcd(x.val, val)};
#endif
    }
};
template <class T>
class SparseTable {
private:
    int n;
    std::vector<std::vector<T>> ST;

public:
    SparseTable(void) {}
    SparseTable(int N) : n(N), ST(N, std::vector<T>(std::__lg(N) + 1)) {}
    template <class InitT>
    SparseTable(std::vector<InitT> &_init) : SparseTable(_init.size()) { init(_init, true); }
    template <class InitT>
    inline void init(std::vector<InitT> &_init, bool internal = false) {
        if (!internal) {
            n = _init.size();
            ST.assign(n, std::vector<T>(std::__lg(n) + 1));
        }
        for (int i = 0; i < n; i++) ST[i][0] = T(_init[i]);
        for (int i = 1; (1 << i) <= n; i++) {
            for (int j = 0; j + (1 << i) - 1 < n; j++) {
                ST[j][i] = ST[j][i - 1] + ST[j + (1 << (i - 1))][i - 1];
            }
        }
    }
    inline T query(int l, int r) { // 0 based
        if (l > r) return T();
        int w = std::__lg(r - l + 1);
        return ST[l][w] + ST[r - (1 << w) + 1][w];
    }
    inline T disjoint_query(int l, int r) {
        T ans = T();
        for (int i = l; i <= r; i += (1 << std::__lg(r - i + 1))) {
            ans = ans + ST[i][std::__lg(r - i + 1)];
        }
        return ans;
    }
};


#line 9 "/Users/alfred/Desktop/Tools/cpp-templates/src/alfred/string/suffix-array.hpp"

class SuffixArray {
private:
    int n;
    std::string s; // internal is 1-index, access is 0-indexed.
    SparseTable<MinInfo<int>> ST;
    std::vector<int> sa, rnk, old, h;

public:
    SuffixArray(std::string S) : n(S.size()), s(S) {
        const int m = n + 1;
        s.insert(s.begin(), ' '), sa.assign(m, 0);
        rnk.assign(m, 0), old.assign(m, 0), h.assign(m, 0);
        for (int i = 1; i <= n; i++) sa[i] = i, rnk[i] = s[i];

        for (int w = 1; w < n; w *= 2) {
            std::copy(rnk.begin(), rnk.end(), old.begin());
            auto cmp = [&](int x, int y) {
                if (old[x] != old[y]) return old[x] < old[y];
                if (y + w > n) return false;
                if (x + w > n) return true;
                return old[x + w] < old[y + w];
            };
            std::sort(std::next(sa.begin()), sa.end(), cmp);
            for (int i = 1; i <= n; i++) {
                rnk[sa[i]] = rnk[sa[i - 1]] + cmp(sa[i - 1], sa[i]);
            }
            if (rnk[sa[n]] == n) break;
        }

        for (int i = 1, k = 0; i <= n; i++) {
            if (rnk[i] == 0) continue;
            if (k != 0) k--;
            while (std::max(i, sa[rnk[i] - 1]) <= n - k &&
                   s[i + k] == s[sa[rnk[i] - 1] + k]) {
                k++;
            }
            h[rnk[i]] = k;
        }
        ST.init(h);
    }
    const std::vector<int> get_h(void) { return h; }
    const std::vector<int> get_sa(void) { return sa; }
    const std::vector<int> get_rnk(void) { return rnk; }
    inline int lcp(int i, int j) { // 0-indexed !
        i = rnk[i + 1], j = rnk[j + 1];
        if (i > j) std::swap(i, j);
        return i == j ? n - i : ST.query(i + 1, j).val;
    }
};


#line 6 "aizu-suffix-array.test.cpp"

std::string S, T;

inline void solve(void) {
    SuffixArray SA(S + '#' + T);
    int n = S.size(), m = T.size(), ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            ans = std::max(ans, SA.lcp(i, j + n + 1));
        }
    }
    std::cout << ans << '\n';
}

int main(int argc, char const *argv[]) {
    optimizeIO();
    while (std::cin >> S >> T) {
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 430
memory_kb: 4000
final_rank: 8

code_snippet: #include <bits/stdc++.h>


using namespace std;
//make -f ../makefile SRC=
/*


*/

//------------------------------------------------------------------------------
bool DEBUG = false;

//------------------------------------------------------------------------------
int lcs(const string& X, const string& Y)
{
    int res = 0;

    int M = X.size();
    int N = Y.size();

    int S[M+1][N+1];
    for (int i=0; i<M+1; i++)
    {
        for (int j=0; j<N+1; j++)
        {
            if (i == 0 || j == 0) S[i][j] = 0;
            else if (X[i-1] == Y[j-1])
            {
                S[i][j] = S[i-1][j-1] + 1;
                res = max(res, S[i][j]);
            }
            else S[i][j] = 0;
        }
    }
    return res;
}

//------------------------------------------------------------------------------
int main()
{
    //DEBUG = true;
    //test(); return 0;
    //--------------------------------------------------------------------------
    string X, Y;
    while (true)
    {
        getline(cin, X);
        if (cin.eof()) break;
        getline(cin, Y);
        int res = lcs(X, Y);
        printf("%d\n", res);
    }

    //--------------------------------------------------------------------------
    return 0;
}
//------------------------------------------------------------------------------
accuracy: 1
time_ms: 90
memory_kb: 66124
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;


int main() {
    string s, t;
    while (cin >> s >> t) {
        vector<vector<int> > dp(s.size(), vector<int>(t.size(), 0));
        int mx = -1;
        for (int i = 0; i < s.size(); i++) {
            for (int j = 0; j < t.size(); j++) {
                if (s[i] != t[j]) {
                    dp[i][j] = 0;
                } else {
                    if (i > 0 && j > 0) dp[i][j] = dp[i - 1][j - 1];
                    dp[i][j]++;
                }
                if (dp[i][j] > mx) {
                    mx = dp[i][j];
                }
            }
        }
        cout << mx << endl;
    }
}
accuracy: 1
time_ms: 240
memory_kb: 65936
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;


int main() {
    string s, t;
    while (cin >> s >> t) {
        vector<vector<int> > dp(s.size(), vector<int>(t.size(), 0));
        int mx = -1;
        int idx = 0;
        for (int i = 0; i < s.size(); i++) {
            for (int j = 0; j < t.size(); j++) {
                if (s[i] != t[j]) {
                    dp[i][j] = 0;
                } else {
                    if (i > 0 && j > 0) dp[i][j] = dp[i - 1][j - 1];
                    dp[i][j]++;
                    if (dp[i][j] > mx) {
                        mx = dp[i][j];
                        idx = i;
                    }
                }
            }
        }
        string ans;
        for (int i = idx; i > idx - mx; i--) {
            ans = s[i] + ans;
        }
        cout << ans.size() << endl;
    }
}
accuracy: 1
time_ms: 180
memory_kb: 65648
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#include <random>
using namespace std;
//#include <atcoder/all>
//using namespace atcoder;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vvvvll = vector<vvvll>;
using vvvvvll = vector<vvvvll>;
using vvvvvvll = vector<vvvvvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvvb = vector<vvb>;
using vvvvb = vector<vvvb>;
using vd = vector<double>;
using vvd = vector<vd>;
using vvvd = vector<vvd>;
using vvvvd = vector<vvvd>;
using vvvvvd = vector<vvvvd>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
using pqr = priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>>;

template<class T>
bool chmax(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

template<class T>
bool chmin(T& p, T q, bool C = 1) {
    if (C == 0 && p == q) {
        return 1;
    }
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

ll gcd(ll(a), ll(b)) {
    if (b == 0)return a;
    ll c = a;
    while (a % b != 0) {
        c = a % b;
        a = b;
        b = c;
    }
    return b;
}


struct dsu {
  public:
    dsu() : _n(0) {}
    dsu(int n) : _n(n), par_size(n, -1) {}

    int merge(int a, int b) {
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-par_size[x] < -par_size[y]) swap(x, y);
        par_size[x] += par_size[y];
        par_size[y] = x;
        return x;
    }
    int merge(pair<ll,ll> p) {
        int a=p.first;
        int b=p.second;
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-par_size[x] < -par_size[y]) swap(x, y);
        par_size[x] += par_size[y];
        par_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        return leader(a) == leader(b);
    }
    bool same(pair<ll,ll> p) {
        int a=p.first;
        int b=p.second;
        return leader(a) == leader(b);
    }

    int leader(int a) {
        if (par_size[a] < 0) return a;
        return par_size[a] = leader(par_size[a]);
    }

    int size(int a) {
        return -par_size[leader(a)];
    }

    vector<vector<int>> groups() {
        std::vector<int> leader_buf(_n), gr_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            gr_size[leader_buf[i]]++;
        }
        std::vector<vector<int>> res(_n);
        for (int i = 0; i < _n; i++) {
            res[i].reserve(gr_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            res[leader_buf[i]].push_back(i);
        }
        res.erase(
            remove_if(res.begin(), res.end(),
                           [&](const vector<int>& v) { return v.empty(); }),
            res.end());
        return res;
    }
  private:
    int _n;
    vector<int> par_size;
};

template <class T> std::vector<int> z_algorithm(const std::vector<T>& s) {
    int n = int(s.size());
    if (n == 0) return {};
    std::vector<int> z(n);
    z[0] = 0;
    for (int i = 1, j = 0; i < n; i++) {
        int& k = z[i];
        k = (j + z[j] <= i) ? 0 : std::min(j + z[j] - i, z[i - j]);
        while (i + k < n && s[k] == s[i + k]) k++;
        if (j + z[j] < i + z[i]) j = i;
    }
    z[0] = n;
    return z;
}

vector<int> z_algorithm(const std::string& s) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return z_algorithm(s2);
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    string A,B;
    while(cin>>A>>B){
        if(A.size()<B.size())swap(A,B);
        ll an=0;
        //string AB=A+B;
        rep(i,A.size()){
            string AB=A.substr(i,A.size()-i)+B;
            auto p=z_algorithm(AB);
            for(ll j=A.size()-i;j<p.size();j++)chmax(an,min(ll(p[j]),ll(A.size()-i)));
        }
        cout<<an<<endl;
    }
    

    
}
accuracy: 1
time_ms: 790
memory_kb: 3500
final_rank: 18

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;

using pii = pair<int, int>;

int main()
{
    string s, t;
    while (cin >> s) {
        cin >> t;
        int m = s.size();
        int ans = 0;
        rep(idx, m) {
            string st = s.substr(idx) + "#" + t;
            int n = st.size();

            vi<int> z(n);
            //z[0] = n;
            int i = 1, len = 0;
            while (i < n) {
                while (i + len < n && st[len] == st[i + len]) len++;
                z[i] = len;
                if (len == 0) {
                    i++;
                    continue;
                }
                int k = 1;
                while (k + z[k] < len) {
                    z[i + k] = z[k];
                    k++;
                }
                len -= k;
                i += k;
            }
            
            for (int i = m - idx; i < n; i++) ans = max(ans, z[i]);
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 3432
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <cmath>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;

using pii = pair<int, int>;

void chmax(int& x, int y) { x = max(x, y); }

int main()
{
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    string s, t;
    while(cin >> s){
        cin >> t;
        int ls = s.size(), lt = t.size();
    
        vi<int> dp(lt + 1);
    
        int ans = 0;
        for (int i = ls - 1; i >= 0; i--) {
            vi<int> prev(lt + 1);
            swap(dp, prev);
            for (int j = lt - 1; j >= 0; j--) {
                if (s[i] == t[j]) {
                    dp[j] = prev[j + 1] + 1;
                    chmax(ans, dp[j]);
                }
            }
        }
    
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3308
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    string s;
    string t;
    while (cin >> s >> t) {
        s = "0" + s;
        t = "0" + t;

        deque<vector<int>> dp;
        dp.push_back(vector<int>(t.length(), 0));
        int max_len = 0;
        for (int i = 1; i < (int)s.length(); ++i) {
            vector<int> sv = dp.front();
            dp.pop_front();
            vector<int> tv(t.length(), 0);
            for (int j = 1; j < (int)t.length(); ++j) {
                if (s[i] == t[j]) {
                    tv[j] = sv[j - 1] + 1;
                    max_len = max(max_len, tv[j]);
                }
            }
            dp.push_back(tv);
        }
        cout << max_len << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3432
final_rank: 6

code_snippet: #include<string.h>
#include<stdio.h>
#define MAXN 4000


char g_a[MAXN + 1];
char g_b[MAXN + 1];


int g_dp[MAXN + 1][MAXN + 1];

void slove()
{
	int alen = strlen(g_a);
	int blen = strlen(g_b);

	int maxlen = 0;

	for (int i = 1; i <= blen; i++)
	{
		for (int j = 1; j <= alen; j++)
		{
			if (g_b[i - 1] == g_a[j - 1])
			{
				g_dp[i][j] = g_dp[i - 1][j - 1] + 1;
				if (maxlen < g_dp[i][j])
					maxlen = g_dp[i][j];
			}
		}
	}

	printf("%d\n", maxlen);
}



int main()
{
	while (1)
	{
		memset(g_a, 0, sizeof(g_a));
		memset(g_b, 0, sizeof(g_b));
		memset(g_dp, 0, sizeof(g_dp));
		if (scanf("%s", g_a) == EOF)
			break;

		scanf("%s", g_b);
		slove();
	}
	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 65248
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

int dp[4444][4444];

int main(void)
{
	int i, j, ans = 0;

	string a, b;
	while (cin >> a >> b) {

    	int alen = a.size(), blen = b.size();
    	a = '#' + a, b = '#' + b;
        ans = 0;
    	for (i = 1; i <= alen; i++)
    		for (j = 1; j <= blen; j++)
    		{
    			if (a[i] == b[j])
    				dp[i][j] = dp[i - 1][j - 1] + 1;
    			else
                    dp[i][j] = 0;
    
    			if (ans < dp[i][j])
    				ans = dp[i][j];
    		}
    
    	printf("%d\n" ,ans);
	}
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 72720
final_rank: 15

code_snippet: #include "bits/stdc++.h"

#define REP(i,num) for(ll i=0;i<(num);++i)
#define FOR(i,c,num) for(ll (i)=(c);(i)<(num);++(i))
#define LOOP(i) while(i--)
#define ALL(c) c.begin(),c.end()
#define PRINTALL(c) for(auto pitr=c.begin();pitr!=c.end();++pitr){cout<<*pitr;if(next(pitr,1)!=c.end())cout<<' ';}cout<<endl;
#define PAIRCOMP(c,comp) [](const pair<ll,ll>& lhs,const pair<ll,ll>& rhs){return lhs.c comp rhs.c;}

using namespace std;
//using ll = long long;
using ll = int;
using ull = unsigned long long;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;

constexpr ll atcoder_mod = 1e9+7;

template<typename T=ll>
T in(){ T x; cin >> x; return (x); }
template<typename T=ll,typename C=vector<T>>
C vecin(int N){ C x(N);REP(i,N){ x[i]=in<T>(); }return x; }
template<typename T=ll,size_t N>
array<T,N> arrin(){array<T,N> x;REP(i,N){ x[i]=in<T>(); }return x;}

void vout(){ cout << endl; }
template<typename Head,typename... Tail>
void vout(Head&& h,Tail&&... t){ cout << ' ' << h;vout(forward<Tail>(t)...); }
void out(){ cout << endl; }
template<typename Head,typename... Tail>
void out(Head&& h,Tail&&... t){ cout << h;vout(forward<Tail>(t)...); }

template<typename T>
bool chmax(T& a,T b){ if(a<b){ a=b;return true; }return false; }
template<typename T>
bool chmin(T& a,T b){ if(a>b){ a=b;return true; }return false; }

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cout<<fixed<<setprecision(10);

	while(true){
		string S,T;
		getline(cin,S);
		if(cin.eof()) break;
		getline(cin,T);
		
		vvll dp(T.length()+1,vll(S.length()+1,0));
		REP(i,T.length()){
			REP(j,S.length()){
				if(S[j]==T[i]){
					dp[i+1][j+1] = dp[i][j]+1;
				}
			}
		}
		ll maxL=0;
		REP(i,T.length()){
			REP(j,S.length()){
				maxL = max(maxL,dp[i+1][j+1]);
			}
		}
		out(maxL);
	}
	return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 65808
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long MOD1 = 1000000007;
const long long MOD2 = 998244353;
typedef long long ll;
typedef pair<long long, long long> P;
const long long INF = 1e18;
const ll MOD = INF;
template <typename T>
void input_arr(vector<T>& A, ll N) {
	for (ll i = 0; i < N; i++) {
		cin >> A[i];
	}
}
template <typename T, typename Q>
void input_arr(vector<pair<T, Q>>& A, ll N) {
	for (ll i = 0; i < N; i++) {
		cin >> A[i].first >> A[i].second;
	}
}
template <typename T>
void input_arr(vector<vector<T>>& A, ll H, ll W) {
	for (ll i = 0; i < H; i++) {
		for (ll j = 0; j < W; j++) {
			cin >> A[i][j];
		}
	}
}
int main() {
	string S, T;
	while (cin >> S >> T) {
		ll ans = 0;
		for (ll i = 0; i < S.size(); i++) {
			ll num = 0, sum = 0;
			for (ll j = 0; j < T.size() && i + j < S.size(); j++) {
				if (S[i + j] == T[j]) {
					sum++;
				}
				else {
					num = max(num, sum);
                  	sum = 0;
				}
			}
          	num = max(num, sum);
			ans = max(ans, num);
		}
      	for (ll i = 0; i < T.size(); i++) {
			ll num = 0, sum = 0;
			for (ll j = 0; j < S.size() && i + j < T.size(); j++) {
				if (T[i + j] == S[j]) {
					sum++;
				}
				else {
					num = max(num, sum);
                  	sum = 0;
				}
			}
          	num = max(num, sum);
			ans = max(ans, num);
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 80
memory_kb: 3276
final_rank: 3

code_snippet: #define _USE_MATH_DEFINES
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<list>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<iomanip>
#include<sstream>
#include<regex>
#include<random>
using namespace std;
#define int long long
#define uint unsigned long long
const int mod=1e9+7;
const int Mod=998244353;
const int inf=mod*mod;
const double eps=1e-9;
int dp[4001][4001];
signed main(){
	string s,t;
	while(cin>>s>>t){
		for(int i=0;i<=s.size();i++)
			for(int j=0;j<=t.size();j++)
				dp[i][j]=0;
		int mx=0;
		for(int i=0;i<s.size();i++){
			for(int j=0;j<t.size();j++){
				if(s[i]==t[j]){
					dp[i+1][j+1]=dp[i][j]+1;
					mx=max(mx,dp[i+1][j+1]);
				}
			}
		}
		cout<<mx<<endl;
	}
}
accuracy: 1
time_ms: 120
memory_kb: 128528
final_rank: 19

code_snippet: #include<iostream>

using namespace std;

int dp[4001][4001];

int main()
{
	string s1,s2;
	while (cin >> s1)
	{
		cin >> s2;
		int ans = 0;
		for (int i = 1; i <= s1.size(); i++)
		    for (int j = 1; j <= s2.size(); j++)
			    dp[i][j] = 0;
		for (int i = 1; i <= s1.size(); i++)
		{
			for (int j = 1; j <= s2.size(); j++)
			{
				if (s1[i - 1] == s2[j - 1])
				{
					dp[i][j] = dp[i - 1][j - 1] + 1;
					ans = max(ans, dp[i][j]);
				}
			}
		}
		cout << ans << endl;
	}

    //system("pause");
}
accuracy: 1
time_ms: 200
memory_kb: 65652
final_rank: 14

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>

using namespace std;

int dp[4001][4001];


int main(int argc, char** argv) {
#if READ_FROM_FILE
	std::ifstream ifs("test0.txt");
	std::cin.rdbuf(ifs.rdbuf());
#endif
	
	while (true) {
		string s, t;
		cin >> s >> t;
		if (s == "") {
			break;
		}
		int n = s.size();
		int m = t.size();
		int max_length = 0;
		for (int i = 0; i < 4001; i++) {
			dp[i][0] = 0;
			dp[0][i] = 0;
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (s[i] == t[j]) {
					dp[i + 1][j + 1] = dp[i][j] + 1;
					max_length = max(max_length, dp[i + 1][j + 1]);
				}
				else {
					dp[i + 1][j + 1] = 0;
				}
			}
		}
		cout << max_length << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 65556
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, N) for (ll i = 0; i < N; i++)

int main()
{

  string a, b;
  while(cin >> a >> b){
  ll alen = a.length();
  ll blen = b.length();
  ll maxv = 0;
  ll cnt = 0;
  rep(i, alen)
  {
    rep(j, blen)
    {
      if(i+j >= alen-1) continue;
      if (a[i + j] == b[j])
      {
        cnt++;
      }
      else
      {
        maxv = max(maxv, cnt);
        cnt = 0;
      }
    }
    maxv = max(maxv, cnt);
    cnt = 0;
  }

  rep(i, alen)
  {
    rep(j, blen)
    {
      if(alen -1 - i - j < 0) continue;

      if (a[alen -1 - i - j] == b[blen - 1 - j])
      {
        cnt++;
      }
      else
      {
        maxv = max(maxv, cnt);
        cnt = 0;
      }
    }
    maxv = max(maxv, cnt);
    cnt = 0;
  }

  cout << maxv << endl;
  }
}
accuracy: 1
time_ms: 140
memory_kb: 3020
final_rank: 7