1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
| #include <bits/stdc++.h>
#define ios cin.tie(nullptr)->sync_with_stdio(false) #define endl '\n'
using namespace std; using i64 = long long;
template <class T, const T P = 0> struct ModInt { static T _Mod; constexpr static T getMod() { return P > 0 ? P : _Mod; } constexpr static void setMod(T Mod) { _Mod = Mod; } constexpr T norm(T val) const { return val < 0 ? val += getMod() : val >= getMod() ? val -= getMod() : val; }
T _val; constexpr ModInt() : ModInt(0) {} constexpr ModInt(T val) : _val(norm(val % getMod())) {} constexpr ModInt &operator=(T rhs) & { return *this = ModInt(rhs); }
explicit constexpr operator T() const { return _val; } constexpr T val() const { return _val; } constexpr ModInt operator-() const { return ModInt(norm(getMod() - _val)); }
constexpr ModInt power(ModInt x, i64 n) const { ModInt res = 1; for (; n; x *= x, n /= 2) { if (n % 2) res *= x; } return res; } constexpr ModInt inv() const { assert(_val != 0); return power(*this, getMod() - 2); }
constexpr ModInt &operator+=(ModInt rhs) & { return _val = norm(_val + rhs.val()), *this; } constexpr ModInt &operator-=(ModInt rhs) & { return _val = norm(_val - rhs.val()), *this; } constexpr ModInt &operator*=(ModInt rhs) & { return _val = 1LL * _val * rhs.val() % getMod(), *this; } constexpr ModInt &operator/=(ModInt rhs) & { return *this *= rhs.inv(); } friend constexpr ModInt operator+(ModInt lhs, ModInt rhs) { return lhs += rhs; } friend constexpr ModInt operator-(ModInt lhs, ModInt rhs) { return lhs -= rhs; } friend constexpr ModInt operator*(ModInt lhs, ModInt rhs) { return lhs *= rhs; } friend constexpr ModInt operator/(ModInt lhs, ModInt rhs) { return lhs /= rhs; }
friend constexpr bool operator<(ModInt lhs, ModInt rhs) { return lhs.val() < rhs.val(); } friend constexpr bool operator==(ModInt lhs, ModInt rhs) { return lhs.val() == rhs.val(); } friend constexpr bool operator!=(ModInt lhs, ModInt rhs) { return lhs.val() != rhs.val(); }
friend istream &operator>>(istream &is, ModInt &x) { i64 val; return is >> val, x = ModInt(val), is; } friend ostream &operator<<(ostream &os, ModInt x) { return os << x.val(); } };
template <class T, const T P> T ModInt<T, P>::_Mod; using MInt = ModInt<int, int(1E9) + 7>;
struct String : public string { char &operator[](int pos) { return string::operator[](pos - 1); } const char &operator[](int pos) const { return string::operator[](pos - 1); } };
template <class T1, class T2> struct ModPair : public pair<T1, T2> { constexpr ModPair() : pair<T1, T2>() {} constexpr ModPair(T1 first, T2 second) : pair<T1, T2>(first, second) {} friend constexpr ModPair operator+(ModPair lhs, const ModPair rhs) { return lhs.first += rhs.first, lhs.second += rhs.second, lhs; } friend constexpr ModPair operator-(ModPair lhs, const ModPair rhs) { return lhs.first -= rhs.first, lhs.second -= rhs.second, lhs; } friend constexpr ModPair operator*(ModPair lhs, const ModPair rhs) { return lhs.first *= rhs.first, lhs.second *= rhs.second, lhs; } };
struct Hash { constexpr static int _Mod1 = 1E9 + 7, _Mod2 = 1E9 + 9; using HashInt1 = ModInt<int, _Mod1>; using HashInt2 = ModInt<int, _Mod2>; using HashPair = ModPair<HashInt1, HashInt2>; constexpr static HashPair _Base = HashPair(HashInt1(137), HashInt2(139));
bool _rev; vector<HashPair> _code, _base; Hash(String &s, bool rev = false) : _rev(rev), _code(s.size() + 2), _base(s.size() + 2) { init(s); } void init(String &s) { if (_rev) { for (int i = s.size(); i >= 1; i--) _code[i] = _code[i + 1] * _Base + HashPair(s[i], s[i]); } else { for (int i = 1; i <= s.size(); i++) _code[i] = _code[i - 1] * _Base + HashPair(s[i], s[i]); } _base[0] = HashPair(1, 1); for (int i = 1; i <= s.size(); i++) _base[i] = _base[i - 1] * _Base; }
HashPair query(int l, int r) const { if (_rev) return _code[l] - _code[r + 1] * _base[r - l + 1]; else return _code[r] - _code[l - 1] * _base[r - l + 1]; } };
void solve() { int n; cin >> n;
String a, b; cin >> a >> b;
n = n * 2 + 1, a += a + '|', b += b + '|'; for (int i = n - 1; i >= 1; i -= 2) { a[i] = a[i / 2], b[i] = b[i / 2]; a[i - 1] = b[i - 1] = '|'; }
int ans = 1; Hash forA(a), backA(a, true), forB(b), backB(b, true); auto check = [&](Hash &h1, Hash &h2, int l1, int r1, int l2, int r2) { return h1.query(l1, r1) == h2.query(l2, r2); }; for (int p = 1; p <= n; p++) { int l1 = 0, r1 = min(p - 1, n - p); while (l1 < r1) { int m = (l1 + r1 + 1) / 2; if (check(forA, backA, p - m, p - 1, p + 1, p + m)) l1 = m; else r1 = m - 1; } ans = max(ans, l1);
int i = p - l1, j = p + l1 - 2; int l2 = 0, r2 = min(i - 1, n - j); while (l2 < r2) { int m = (l2 + r2 + 1) / 2; if (check(forA, backB, i - m, i - 1, j + 1, j + m)) l2 = m; else r2 = m - 1; } ans = max(ans, l1 + l2); } for (int p = 1; p <= n; p++) { int l1 = 0, r1 = min(p - 1, n - p); while (l1 < r1) { int m = (l1 + r1 + 1) / 2; if (check(forB, backB, p - m, p - 1, p + 1, p + m)) l1 = m; else r1 = m - 1; } ans = max(ans, l1);
int j = p - l1 + 2, k = p + l1; int l2 = 0, r2 = min(j - 1, n - k); while (l2 < r2) { int m = (l2 + r2 + 1) / 2; if (check(forA, backB, j - m, j - 1, k + 1, k + m)) l2 = m; else r2 = m - 1; } ans = max(ans, l1 + l2); } cout << ans << endl; }
int main() { ios; int T = 1; while (T--) solve(); return 0; }
|