Sunday, March 24, 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. #define ll          long long int  
  6. #define ull         unsigned long long int  
  7.   
  8. static const int maxn = 1e5 + 5;  
  9. static const int mod = 1e9 + 123;  
  10.   
  11. int gen_base(const int before, const int after)  
  12. {  
  13.       auto seed = chrono::high_resolution_clock::now().time_since_epoch().count();  
  14.       mt19937 mt_rand(seed);  
  15.       int base = uniform_int_distribution <int> (before+1, after) (mt_rand);  
  16.       return base % 2 == 0 ? base - 1 : base;  
  17. }  
  18.   
  19. int pow1[maxn];  
  20. ull pow2[maxn];  
  21. int base;  
  22.   
  23. void preCalc()  
  24. {  
  25.       assert(base < mod);  
  26.       pow1[0] = 1;  
  27.       pow2[0] = 1;  
  28.       for (int i = 1; i < maxn; i++)  
  29.       {  
  30.             pow1[i] = (1LL * pow1[i-1] * base % mod);  
  31.             pow2[i] = (pow2[i-1] * base);  
  32.       }  
  33. }  
  34.   
  35. struct Hash  
  36. {  
  37.       vector <ll> pref1;  
  38.       vector <ull> pref2;  
  39.       Hash() {}  
  40.       Hash(const string &s) : pref1(s.size() + 1u, 0), pref2(s.size() + 1u, 0)  
  41.       {  
  42.             assert(base < mod);  
  43.             int n = s.size();  
  44.             for (int i = 0; i < n; i++)  
  45.             {  
  46.                   assert(base > s[i]);  
  47.                   pref1[i+1] = (pref1[i] + 1LL * s[i] * pow1[i]) % mod;  
  48.                   pref2[i+1] = pref2[i] + s[i] * pow2[i];  
  49.             }  
  50.       }  
  51.       // Polynomial hash of subsequence [pos, pos+len)  
  52.       // If mxPow != 0, value automatically multiply on base in needed power.  
  53.       // Finally base ^ mxPow  
  54.       // 0 - Indexed  
  55.       pair <ll, ull> getHash(const int pos, const int len, const int mxPow = 0)  
  56.       {  
  57.             ll hash1 = pref1[pos + len] - pref1[pos];  
  58.             ull hash2 = pref2[pos + len] - pref2[pos];  
  59.             if (hash1 < 0) hash1 += mod;  
  60.             if (mxPow != 0)  
  61.             {  
  62.                   hash1 = 1LL * hash1 * pow1[mxPow - (pos + len - 1)] % mod;  
  63.                   hash2 = hash2 * pow2[mxPow - (pos + len - 1)];  
  64.             }  
  65.             return make_pair(hash1, hash2);  
  66.       }  
  67. };  
  68.   
  69.   
  70. int main()  
  71. {  
  72.       ios_base::sync_with_stdio(false);  
  73.       cin.tie(nullptr);  
  74.       cout << fixed << setprecision(15);  
  75.       #ifndef ONLINE_JUDGE  
  76.             freopen("in.txt""r", stdin);  
  77.       #endif // ONLINE_JUDGE  
  78.   
  79.       base = gen_base(256, mod);  
  80.       preCalc();  
  81.       int tc;  
  82.       cin >> tc;  
  83.       for (int tcase = 1; tcase <= tc; tcase++)  
  84.       {  
  85.             int k;  
  86.             string s, revs;  
  87.             cin >> k >> s;  
  88.             revs = s;  
  89.             reverse(revs.begin(), revs.end());  
  90.             int len = s.size();  
  91.             const int mxPow = len;  
  92.             Hash hash_s = Hash(s);  
  93.             Hash hash_revs = Hash(revs);  
  94.             ll ans = 0;  
  95.             int i = 0, j = 0;  
  96.             for ( ; j < len; j++)  
  97.             {  
  98.                   int nlen = j - i + 1;  
  99.                   if (nlen < k)  
  100.                   {  
  101.                         ans += nlen;  
  102.                         continue;  
  103.                   }  
  104.                   // check for k length palindrome  
  105.                   int start_in_s = j - k + 1;  
  106.                   int start_in_revs = len - j - 1;  
  107.                   if (start_in_s >= 0 && hash_s.getHash(start_in_s, k, mxPow) == hash_revs.getHash(start_in_revs, k, mxPow))  
  108.                   {  
  109.                         i = start_in_s + 1;  
  110.                         ans += j - i + 1;  
  111.                         continue;  
  112.                   }  
  113.                   // check for k+1 length palindrome  
  114.                   start_in_s -= 1;  
  115.                   if (start_in_s >= 0 && hash_s.getHash(start_in_s, k+1, mxPow) == hash_revs.getHash(start_in_revs, k+1, mxPow))  
  116.                   {  
  117.                         i = start_in_s + 1;  
  118.                         ans += j - i + 1;  
  119.                         continue;  
  120.                   }  
  121.                   ans += j - i + 1;  
  122.             }  
  123.             cout << ans << '\n';  
  124.       }  
  125. }  

No comments:

Post a Comment

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