/*
    Problem "Ada and Terramorphing" on spoj.com
    
    Solution: polynomial hash, sort, binary search, O(n log(n)^2)
*/

#include <stdio.h>
#include <cassert>
#include <algorithm>
#include <vector>
#include <random>
#include <chrono>
#include <string>
#include <iostream>

typedef unsigned long long ull;

// Generate random base in (before, after) open interval:
int gen_base(const int before, const int after) {
    auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
    std::mt19937 mt_rand(seed ^ ull(new ull));
    int base = std::uniform_int_distribution<int>(before+1, after)(mt_rand);
    return base % 2 == 0 ? base-1 : base;
}
 
struct PolyHash {
    // -------- Static variables --------
    static const int MOD = 2147483647;
    static std::vector<int> pow1;        // powers of base modulo mod
    static std::vector<ull> pow2;        // powers of base modulo 2^64
    static int base;                     // base (point of hashing)
 
    // --------- Static functons --------
    static inline int sub(int a, int b) { 
    	// Sub from `a` value `b` modulo mod (0 <= a < MOD, 0 <= b < MOD)
        return (a -= b) < 0 ? a + MOD : a;
    }
 
    static inline int mod(ull x) {
        x = (x >> 31) + (x & MOD);
        return int((x >> 31) + (x & MOD));
    }
 
    // -------------- Variables of class -------------
    std::vector<int> pref1; // Hash on prefix modulo mod
    std::vector<ull> pref2; // Hash on prefix modulo 2^64
 
    // Cunstructor from vector:
    PolyHash(const std::vector<int>& s)
        : pref1(s.size()+1u, 0)
        , pref2(s.size()+1u, 0)
    {
        while (pow1.size() <= s.size()) { // Pre-compute powers of base:
            pow1.push_back(mod((ull)pow1.back() * base));
            pow2.push_back(pow2.back() * base);
        }
        for (int i = 0; i < (int)s.size(); ++i) { // Fill arrays with polynomial hashes on prefix:
            pref1[i+1] = mod(pref1[i] + (ull)s[i] * pow1[i]);
            pref2[i+1] = pref2[i] + s[i] * pow2[i];
        }
    }
 
    // Polynomial hash of subsequence [pos, pos+len)
    // If mxPow != 0, value automatically multiply on base in needed power. Finally base ^ mxPow
    inline std::pair<int, ull> operator()(const int pos, const int len, const int mxPow = 0) const {
        int hash1 = sub(pref1[pos+len], pref1[pos]);
        ull hash2 = pref2[pos+len] - pref2[pos];
        if (mxPow != 0) {
            hash1 = mod((ull)hash1 * pow1[mxPow-(pos+len-1)]);
            hash2 *= pow2[mxPow-(pos+len-1)];
        }
        return std::make_pair(hash1, hash2);
    }
};
 
// Init static variables of PolyHash class:
int PolyHash::base((int)1e9+7);    
std::vector<int> PolyHash::pow1{1};
std::vector<ull> PolyHash::pow2{1};

void gen(int n, std::string& s, std::string& t) {
    s.assign(n, '?');
    t.assign(n, '?');
    for (int i = 0, j = n-1; i <= j; ++i, --j) {
        t[j] = s[i] = 'v';
    }
    for (int i = 0; i < n; ++i) {
        s[i] = s[i] == '?' ? '~' : s[i];
        t[i] = t[i] == '?' ? '-' : t[i];
    }
}

void input(std::string& s, std::string& t) {
    char buf[1+1000000];
    scanf("%1000000s", buf);
    s = buf;
    scanf("%1000000s", buf);
    t = buf;
}

int solve(int low, int high, const std::vector<int>& a, const std::vector<int>& b) {
    high = std::min(high, std::min((int)a.size()+1, (int)b.size()+1));
    
    // Calculate mxPow:
    const int mxPow = (int)std::max(a.size(), b.size());
    
    // Create hashing objects from strings:
    PolyHash hash_a(a), hash_b(b);
    
    // Binary search by length of same subsequence:    
    while (high - low > 1) {
        int mid = (low + high) / 2;
        std::vector<std::pair<int,ull>> hashes;
        for (int i = 0; i + mid - 1 < (int)a.size(); ++i) {
            hashes.push_back(hash_a(i,mid, mxPow));
        }
        std::sort(hashes.begin(), hashes.end());
        bool success = false;
        for (int i = 0; i + mid - 1 < (int)b.size(); ++i) {
            if (std::binary_search(hashes.begin(), hashes.end(), hash_b(i, mid, mxPow))) {
                success = true;
                break;
            }
        }
        if (success) {
            low = mid;
        } else {
            high = mid;
        }
    }
    return low;
}

int code(char c) {
    if (c == 'v') return 0;
    if (c == '^') return 1;
    if (c == '~') return 2;
    assert(c == '-');
    return 3;
}

int main() {
    // Gen random base of hashing:
    PolyHash::base = gen_base(1e6, PolyHash::MOD);
    
    std::string a, b;
    input(a,b);
    //gen(1000000, a, b);
    
    // Convert input strings to 1-width sequences:
    std::vector<int> s1(a.size()), t1(b.size());
    for (int i = 0; i < (int)s1.size(); ++i) s1[i] = code(a[i]);
    for (int i = 0; i < (int)t1.size(); ++i) t1[i] = code(b[i]);
    
    // If we can solve slow, just solve:
    if (std::min(s1.size(),t1.size()) <= 2000u) {
        for (auto& it : s1) it++;
        for (auto& it : t1) it++;
        std::cout << solve(0, (int)std::min(s1.size(),t1.size())+1, s1, t1);
        return 0;
    }
    
    // Convert input strings to 4-width sequences:
    std::vector<int> s2(a.size() / 4, 1), t2(b.size() / 4, 1);
    for (int i = 0; i < (int)s1.size(); ++i) {
        s2[i / 4] += (s1[i] << 2 * (i % 4));
    }
    for (int i = 0; i < (int)t1.size(); ++i) {
        t2[i / 4] += (t1[i] << 2 * (i % 4));
    }
    
    // Get answer for 4-width sequences:
    int max1 = solve(0, (int)std::min(s2.size(), t2.size())+1, s2, t2);
    // Get answer for 1-width sequences:
    for (auto& it : s1) it++;
    for (auto& it : t1) it++;
    std::cout << solve(4 * max1, 4 * max1 + 8, s1, t1);
    return 0;
}