Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- const int MX = 200000;
- vector<long long> primes = {999983, 999979};
- vector<long long> MODS = {1000000009, 1000000007};
- long long extendeEuclid ( long long A, long long B, long long *X, long long *Y ){
- long long x2, y2, x1, y1, x, y, r2, r1, q, r;
- x2 = 1; y2 = 0; x1 = 0; y1 = 1;
- for (r2 = A, r1 = B; r1 != 0; r2 = r1, r1 = r, x2 = x1, y2 = y1, x1 = x, y1 = y ) {
- q = r2 / r1; r = r2 % r1;
- x = x2 - (q * x1); y = y2 - (q * y1);
- }
- *X = x2; *Y = y2;
- return r2;
- }
- long long modInv ( long long a, long long m ) {
- long long x, y;
- long long _ = extendeEuclid( a, m, &x, &y );
- x %= m;
- if ( x < 0 ) x += m;
- return x;
- }
- long long powers[2][MX], powersInv[2][MX];
- string S[2];
- int N[2];
- long long hashes[2][2][MX];
- long long rangeHash(int hashID, int strID, int lft, int rgt) {
- long long ret = (hashes[hashID][strID][rgt] -
- hashes[hashID][strID][lft-1]*powersInv[hashID][lft-1]) % MODS[hashID];
- if (ret < 0) ret += MODS[hashID];
- return ret;
- }
- multiset<pair<long long, long long> > possible;
- bool check(int len) {
- cout << "len:" << len << endl;
- if (!len) return true;
- possible.clear();
- for (int i = 1, j = len; j <= N[0]; i ++, j ++) {
- possible.insert({rangeHash(0, 0, i, j), rangeHash(1, 0, i, j)});
- }
- // for (auto u: possible) {
- // cout << "(" << u.first << " " << u.second << ")\n";
- // }
- for (int i = 1, j = len; j <= N[1]; i ++, j ++) {
- pair<long long, long long> key = {rangeHash(0, 1, i, j), rangeHash(1, 1, i, j)};
- if (possible.find(key) != possible.end()) {
- return true;
- }
- }
- return false;
- }
- int main() {
- freopen("data.in", "r", stdin);
- ios_base::sync_with_stdio(0); cin.tie(0);
- cin >> S[0] >> S[1];
- N[0] = S[0].size(), N[1] = S[1].size();
- cout << "N0:" << N[0] << " N1:" << N[1] << endl;
- vector<long long> primesInv;
- for (int i = 0; i < 2; i ++)
- primesInv.push_back(modInv(primes[i], MODS[i]));
- // cout << "movi1:" << primesInv[0] << " movi2:" << primesInv[1] << endl;
- powers[0][0] = powers[1][0] = powersInv[0][0] = powersInv[1][0] = 1;
- for (int j = 1; j < MX; j ++) {
- for (int i = 0; i < 2; i ++) {
- powers[i][j] = (powers[i][j-1]*primes[i]) % MODS[i];
- powersInv[i][j] = (powersInv[i][j-1]*primesInv[i]) % MODS[i];
- }
- }
- for (int i = 0; i < 2; i ++) { // over string
- for (int j = 1; j < N[i]; j ++) { // over length
- for (int k = 0; k < 2; k ++) { // over primes-hash
- hashes[k][i][j] = (hashes[k][i][j-1] + powers[k][j-1]*S[i][j-1]) % MODS[k];
- }
- }
- }
- int lo = 0, hi = min(N[0], N[1]), ans = -1, mid;
- while (lo <= hi) {
- mid = (lo+hi) / 2;
- if (check(mid)) {
- ans = mid;
- lo = mid + 1;
- } else {
- hi = mid - 1;
- }
- }
- cout << ans;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement