Advertisement
dipBRUR

Longest Common Substring

Oct 6th, 2018
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.07 KB | None | 0 0
  1. // Problem : 1517. Freedom of Choice
  2. #include <stdio.h>
  3. #include <cassert>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <random>
  7. #include <chrono>
  8. #include <string>
  9.  
  10. using namespace std;
  11.  
  12. typedef unsigned long long ull;
  13.  
  14. // Generate random base in (before, after) open interval:
  15. int gen_base(const int before, const int after)
  16. {
  17.     auto seed = chrono::high_resolution_clock::now().time_since_epoch().count();
  18.     mt19937 mt_rand(seed);
  19.     int base = uniform_int_distribution<int>(before+1, after)(mt_rand);
  20.     return base % 2 == 0 ? base-1 : base;
  21. }
  22.  
  23. struct PolyHash
  24. {
  25.     // -------- Static variables --------
  26.     static const int mod = (int)1e9+123; // prime mod of polynomial hashing
  27.     static vector<int> pow1;        // powers of base modulo mod
  28.     static vector<ull> pow2;        // powers of base modulo 2^64
  29.     static int base;                     // base (point of hashing)
  30.  
  31.     // --------- Static functons --------
  32.     static inline int diff(int a, int b)
  33.     {
  34.         // Difference between "a" and "b" modulo mod (0 <= a < mod, 0 <= b < mod)
  35.         return (a -= b) < 0 ? a + mod : a;
  36.     }
  37.  
  38.     // -------------- Variables of class -------------
  39.     vector<int> pref1; // Hash on prefix modulo mod
  40.     vector<ull> pref2; // Hash on prefix modulo 2^64
  41.  
  42.     // Cunstructor from string:
  43.     PolyHash(const string& s) : pref1(s.size()+1u, 0), pref2(s.size()+1u, 0)
  44.     {
  45.         assert(base < mod);
  46.         const int n = s.size(); // Firstly calculated needed power of base:
  47.         while ((int)pow1.size() <= n)
  48.         {
  49.             pow1.push_back(1LL * pow1.back() * base % mod);
  50.             pow2.push_back(pow2.back() * base);
  51.         }
  52.         for (int i = 0; i < n; ++i) { // Fill arrays with polynomial hashes on prefix
  53.             assert(base > s[i]);
  54.             pref1[i+1] = (pref1[i] + 1LL * s[i] * pow1[i]) % mod;
  55.             pref2[i+1] = pref2[i] + s[i] * pow2[i];
  56.         }
  57.     }
  58.  
  59.     // Polynomial hash of subsequence [pos, pos+len)
  60.     // If mxPow != 0, value automatically multiply on base in needed power.
  61.     // Finally base ^ mxPow
  62.     inline pair<int, ull> operator () (const int pos, const int len, const int mxPow = 0) const
  63.     {
  64.         int hash1 = pref1[pos+len] - pref1[pos];
  65.         ull hash2 = pref2[pos+len] - pref2[pos];
  66.         if (hash1 < 0) hash1 += mod;
  67.  
  68.  
  69.         if (mxPow != 0)
  70.         {
  71.             hash1 = 1LL * hash1 * pow1[mxPow-(pos+len-1)] % mod;
  72.             hash2 = hash2 * pow2[mxPow-(pos+len-1)];
  73.         }
  74.         return make_pair(hash1, hash2);
  75.     }
  76. };
  77.  
  78. // Init static variables of PolyHash class:
  79. int PolyHash::base((int)1e9+7);
  80. vector<int> PolyHash::pow1{1};
  81. vector<ull> PolyHash::pow2{1};
  82.  
  83. int main()
  84. {
  85.     //freopen("in.txt", "r", stdin);
  86.  
  87.     // Input:
  88.     int n;
  89.     scanf("%d", &n);
  90.     char buf[1+100000];
  91.     scanf("%100000s", buf);
  92.     string a(buf);
  93.     scanf("%100000s", buf);
  94.     string b(buf);
  95.  
  96.     // Calculate max neede power of base:
  97.     const int mxPow = max((int)a.size(), (int)b.size());
  98.  
  99.     // Gen random base of hashing:
  100.     PolyHash::base = gen_base(256, PolyHash::mod);
  101.  
  102.     // Create hashing objects from strings:
  103.     PolyHash hash_a(a), hash_b(b);
  104.  
  105.     // Binary search by length of same subsequence:
  106.     int pos = -1, low = 0, high = std::min(a.size(), b.size())+1;
  107.     while (high - low > 1)
  108.     {
  109.         int mid = (low + high) / 2;
  110.         vector< pair<int,ull> > hashes;
  111.         for (int i = 0; i + mid <= n; i++)
  112.         {
  113.             hashes.push_back(hash_a(i, mid, mxPow));
  114.         }
  115.         sort(hashes.begin(), hashes.end());
  116.         int p = -1;
  117.         for (int i = 0; i + mid <= n; i++)
  118.         {
  119.             if (binary_search(hashes.begin(), hashes.end(), hash_b(i, mid, mxPow)))
  120.             {
  121.                 p = i;
  122.                 break;
  123.             }
  124.         }
  125.         if (p >= 0)
  126.         {
  127.             low = mid;
  128.             pos = p;
  129.         }
  130.         else
  131.         {
  132.             high = mid;
  133.         }
  134.     }
  135.     assert(pos >= 0);
  136.     // Output answer:
  137.     printf("%s", b.substr(pos, low).c_str());
  138.     return 0;
  139. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement