Saturday, September 21, 2019

[Codemarshal] C. Votka and String

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : C. Votka and String
Source            : Codemarshal
                    Eid Punormiloni Contest 2016
Category          : String, Data Structure
Algorithm         : Hashing, Binary Indexed Tree
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. #define int         long long int  
  6. #define endl       '\n'  
  7.   
  8. static const int maxn = 2e5 + 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, after)(mt_rand);  
  16.       return base % 2 == 0 ? base - 1 : base;  
  17. }  
  18.   
  19. long long pow1[maxn];  
  20. unsigned long long 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 <long long> pref1;  
  38.       vector <unsigned long long> 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.       pair <long long, unsigned long long> getHash(const int pos, const int len, const int mxPow = 0)  
  52.       {  
  53.             long long hash1 = pref1[pos + len] - pref1[pos];  
  54.             unsigned long long hash2 = pref2[pos + len] - pref2[pos];  
  55.             if (hash1 < 0) hash1 += mod;  
  56.             if (mxPow != 0)  
  57.             {  
  58.                   hash1 = 1LL * hash1 * pow1[mxPow - (pos + len - 1)] % mod;  
  59.                   hash2 = hash2 * pow2[mxPow - (pos + len - 1)];  
  60.             }  
  61.             return make_pair(hash1, hash2);  
  62.       }  
  63. };  
  64.   
  65.   
  66. int Tree[maxn];  
  67. int N;  
  68.   
  69. void update(int pos, int val)  
  70. {  
  71.       while (pos <= N)  
  72.       {  
  73.             Tree[pos] += val;  
  74.             pos += (pos & -pos);  
  75.       }  
  76. }  
  77.   
  78. void range_update(int l, int r, int val)  
  79. {  
  80.       update(l, val);  
  81.       update(r + 1, -val);  
  82. }  
  83.   
  84. int query(int pos)  
  85. {  
  86.       int sum = 0;  
  87.       while (pos > 0)  
  88.       {  
  89.             sum += Tree[pos];  
  90.             pos -= (pos & -pos);  
  91.       }  
  92.       return sum;  
  93. }  
  94.   
  95. signed main()  
  96. {  
  97.       ios_base::sync_with_stdio(false);  
  98.       cin.tie(nullptr);  
  99.       cout.tie(nullptr);  
  100.   
  101. //      #ifndef ONLINE_JUDGE  
  102. //            freopen("in.txt", "r", stdin);  
  103. //      #endif // ONLINE_JUDGE  
  104.   
  105.       base = gen_base(256, mod);  
  106.       preCalc();  
  107.   
  108.       int tc;  
  109.       cin >> tc;  
  110.       for (int tcase = 1; tcase <= tc; tcase++)  
  111.       {  
  112.             string s;  
  113.             cin >> s;  
  114.             int n;  
  115.             cin >> n;  
  116.             vector <int> queries(n);  
  117.             for (int &x : queries) cin >> x;  
  118.             Hash hash_s(s);  
  119.             int len = s.size();  
  120.             N = len;  
  121.             int mxPow = len;  
  122.             for (int i = 1; i < len; i++)  
  123.             {  
  124.                   pair <long long, unsigned long long> hashPrefix;  
  125.                   pair <long long, unsigned long long> hashSuffix;  
  126.                   int lo = i;  
  127.                   int hi = len - 1;  
  128.                   int id = -1;  
  129.                   while (lo <= hi)  
  130.                   {  
  131.                         int mid = lo + hi >> 1;  
  132.                         int prefixLength = mid - i + 1;  
  133.                         hashPrefix = hash_s.getHash(0, prefixLength, mxPow);  
  134.                         hashSuffix = hash_s.getHash(i, prefixLength, mxPow);  
  135.                         if (hashPrefix == hashSuffix) id = mid, lo = mid + 1;  
  136.                         else hi = mid - 1;  
  137.                   }  
  138.                   if (id == -1) continue;  
  139.                   int validLen = id - i + 1;  
  140.                   range_update(1, validLen, 1);  
  141.             }  
  142.             for (int i = 0; i < n; i++)  
  143.             {  
  144.                   int x = queries[i];  
  145.                   int ans;  
  146.                   if (x == 0) ans = len;  
  147.                   else ans = query(x) + (x <= len);  
  148.                   cout << ans << " \n"[i + 1 == n];  
  149.             }  
  150.             fill(begin(Tree), end(Tree), 0);  
  151.       }  
  152. }  

No comments:

Post a Comment

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