Tuesday, January 22, 2019

[Gym] J - Non Super Boring Substring

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : J - Non Super Boring Substring 
Source            : Codeforces Gym
Category          : String
Algorithm         : Hashing
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. typedef long long               ll;  
  6. typedef unsigned long long      ull;  
  7.   
  8. // Generate random base in (before, after) open interval:  
  9. int gen_base(const int before, const int after)  
  10. {  
  11.       auto seed = chrono::high_resolution_clock::now().time_since_epoch().count();  
  12.       mt19937 mt_rand(seed);  
  13.       int base = uniform_int_distribution <int> (before+1, after) (mt_rand);  
  14.       return base % 2 == 0 ? base - 1 : base;  
  15. }  
  16.   
  17. struct PolyHash  
  18. {  
  19.       //-------- Static variables ---------//  
  20.       static const int mod = (int)1e9+123; // prime mod of polynomial hashing  
  21.       static vector <int> pow1;            // powers of base modulo mod  
  22.       static vector <ull> pow2;            // powers of base modulo 2^64  
  23.       static int base;                     // base (point of hashing)  
  24.       //-------- Static Functions --------//  
  25.       static inline int diff(int a, int b)  
  26.       {  
  27.             // Difference between "a" and "b" modulo mod (0 <= a < mod, 0 <= b < mod)  
  28.             return (a -= b) < 0 ? a + mod : a;  
  29.       }  
  30.       //-------- Variables of class ------//  
  31.       vector <int> pref1; // Hash on prefix modulo mod  
  32.       vector <ull> pref2; // Hash on prefix modulo 2^64  
  33.       // Construct from string:  
  34.       PolyHash(const string &s) : pref1(s.size() + 1u, 0), pref2(s.size() + 1u, 0)  
  35.       {  
  36.             assert(base < mod);  
  37.             const int n = s.size(); // Firstly calculated needed power of base:  
  38.             while((int)pow1.size() <= n)  
  39.             {  
  40.                   pow1.emplace_back(1LL * pow1.back() * base % mod);  
  41.                   pow2.emplace_back(pow2.back() * base);  
  42.             }  
  43.             for (int i = 0; i < n; i++) // Fill arrays with polynomial hashes on prefix  
  44.             {  
  45.                   assert(base > s[i]);  
  46.                   pref1[i+1] = (pref1[i] + 1LL * s[i] * pow1[i]) % mod;  
  47.                   pref2[i+1] = pref2[i] + s[i] * pow2[i];  
  48.             }  
  49.       }  
  50.       // Polynomial hash of subsequence [pos, pos+len)  
  51.       // If mxPow != 0, value automatically multiply on base in needed power.  
  52.       // Finally base ^ mxPow  
  53.       inline pair<int, ull> operator () (const int pos, const int len, const int mxPow = 0) const  
  54.       {  
  55.             int hash1 = pref1[pos+len] - pref1[pos];  
  56.             ull hash2 = pref2[pos+len] - pref2[pos];  
  57.             if (hash1 < 0) hash1 += mod;  
  58.             if (mxPow != 0)  
  59.             {  
  60.                   hash1 = 1LL * hash1 * pow1[mxPow-(pos+len-1)] % mod;  
  61.                   hash2 = hash2 * pow2[mxPow-(pos+len-1)];  
  62.             }  
  63.             return make_pair(hash1, hash2);  
  64.       }  
  65. };  
  66.   
  67. int PolyHash::base((int)1e9+7);  
  68. vector <int> PolyHash::pow1{1};  
  69. vector <ull> PolyHash::pow2{1};  
  70.   
  71. int main()  
  72. {  
  73.       // freopen("in.txt", "r", stdin);  
  74.   
  75.       PolyHash::base = gen_base(256, PolyHash::mod);  
  76.       int tc;  
  77.       cin >> tc;  
  78.       for (int tcase = 1; tcase <= tc; tcase++)  
  79.       {  
  80.             int k;  
  81.             string s, revs;  
  82.             cin >> k >> s;  
  83.             revs = s;  
  84.             reverse(revs.begin(), revs.end());  
  85.             int len = s.size();  
  86.             const int mxPow = len;  
  87.             // PolyHash::base = gen_base(256, PolyHash::mod);  
  88.             PolyHash hash_s(s), hash_revs(revs);  
  89.             ll ans = 0;  
  90.             int i = 0, j = 0;  
  91.             for ( ; j < len; j++)  
  92.             {  
  93.                   int nlen = j - i + 1;  
  94.                   if (nlen < k)  
  95.                   {  
  96.                         ans += nlen;  
  97.                         continue;  
  98.                   }  
  99.                   // check for k length palindrome  
  100.                   int start_in_s = j - k + 1;  
  101.                   int start_in_revs = len - j - 1;  
  102.                   if (start_in_s >= 0 && hash_s(start_in_s, k, mxPow) == hash_revs(start_in_revs, k, mxPow))  
  103.                   {  
  104.                         i = start_in_s + 1;  
  105.                         ans += j - i + 1;  
  106.                         continue;  
  107.                   }  
  108.                   // check for k+1 length  
  109.                   start_in_s -= 1;  
  110.                   if (start_in_s >= 0 && hash_s(start_in_s, k+1, mxPow) == hash_revs(start_in_revs, k+1, mxPow))  
  111.                   {  
  112.                         i = start_in_s + 1;  
  113.                         ans += j - i + 1;  
  114.                         continue;  
  115.                   }  
  116.                   ans += j - i + 1;  
  117.             }  
  118.             cout << ans << "\n";  
  119.       }  
  120. }  

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.