Sunday, March 24, 2019

[UVA] 10860 - Many a Little makes a Mickle

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : 10860 - Many a Little makes a Mickle
Source            : UVA Online Judge
Category          : String, DP
Algorithm         : Hashing, DP
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 = 1e4 + 5;  
  9. static const int mod = 1e9 + 123;  
  10. static const int inf = 1e8;  
  11.   
  12. int gen_base(const int before, const int after)  
  13. {  
  14.       auto seed = chrono::high_resolution_clock::now().time_since_epoch().count();  
  15.       mt19937 mt_rand(seed);  
  16. //      mt19937 rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());  
  17.       int base = uniform_int_distribution <int> (before+1, after) (mt_rand);  
  18.       return base % 2 == 0 ? base - 1 : base;  
  19. }  
  20.   
  21. int pow1[maxn];  
  22. ull pow2[maxn];  
  23. int base;  
  24.   
  25. void preCalc()  
  26. {  
  27.       assert(base < mod);  
  28.       pow1[0] = 1;  
  29.       pow2[0] = 1;  
  30.       for (int i = 1; i < maxn; i++)  
  31.       {  
  32.             pow1[i] = (1LL * pow1[i-1] * base % mod);  
  33.             pow2[i] = (pow2[i-1] * base);  
  34.       }  
  35. }  
  36.   
  37. struct Hash  
  38. {  
  39.       vector <ll> pref1;  
  40.       vector <ull> pref2;  
  41.       Hash() {}  
  42.       Hash(const string &s) : pref1(s.size() + 1u, 0), pref2(s.size() + 1u, 0)  
  43.       {  
  44.             assert(base < mod);  
  45.             int n = s.size();  
  46.             for (int i = 0; i < n; i++)  
  47.             {  
  48.                   assert(base > s[i]);  
  49.                   pref1[i+1] = (pref1[i] + 1LL * s[i] * pow1[i]) % mod;  
  50.                   pref2[i+1] = pref2[i] + s[i] * pow2[i];  
  51.             }  
  52.       }  
  53.       // Polynomial hash of subsequence [pos, pos+len)  
  54.       // If mxPow != 0, value automatically multiply on base in needed power.  
  55.       // Finally base ^ mxPow  
  56.       // 0 - Indexed  
  57.       pair <ll, ull> getHash(const int pos, const int len, const int mxPow = 0)  
  58.       {  
  59.             ll hash1 = pref1[pos + len] - pref1[pos];  
  60.             ull hash2 = pref2[pos + len] - pref2[pos];  
  61.             if (hash1 < 0) hash1 += mod;  
  62.             if (mxPow != 0)  
  63.             {  
  64.                   hash1 = 1LL * hash1 * pow1[mxPow - (pos + len - 1)] % mod;  
  65.                   hash2 = hash2 * pow2[mxPow - (pos + len - 1)];  
  66.             }  
  67.             return make_pair(hash1, hash2);  
  68.       }  
  69. };  
  70.   
  71. #define pii         pair <int, ull>  
  72.   
  73. Hash hash_s;  
  74. Hash hash_p[120];  
  75. string s, p[120];  
  76. int n, len, mxPow;  
  77.   
  78. int dp[maxn];  
  79. bool memoize[maxn];  
  80.   
  81. int solve(int pos)  
  82. {  
  83.       if (pos >= len) return 0;  
  84.       int &ret = dp[pos];  
  85.       bool &mem = memoize[pos];  
  86.       if (mem) return ret;  
  87.       mem = 1;  
  88.       int mini = inf;  
  89.       for (int i = 0; i < n+n; i++)  
  90.       {  
  91.             int len_p = p[i].length();  
  92.             if (pos + len_p > len) continue;  
  93.             pii hsh_s = hash_s.getHash(pos, len_p, mxPow);  
  94.             pii hsh_p = hash_p[i].getHash(0, len_p, mxPow);  
  95.             bool same = (hsh_s == hsh_p);  
  96.             if (same)  
  97.             {  
  98.                   int go = 1 + solve(pos+len_p);  
  99.                   if (go < mini) mini = go;  
  100.             }  
  101.       }  
  102.       return ret = mini;  
  103. }  
  104.   
  105. int main()  
  106. {  
  107.       ios_base::sync_with_stdio(false);  
  108.       cin.tie(nullptr);  
  109.       cout << fixed << setprecision(15);  
  110.       #ifndef ONLINE_JUDGE  
  111.             freopen("in.txt""r", stdin);  
  112.       #endif // ONLINE_JUDGE  
  113.   
  114.       base = gen_base(256, mod);  
  115.       preCalc();  
  116.       int tc;  
  117.       cin >> tc;  
  118.       for (int tcase = 1; tcase <= tc; tcase++)  
  119.       {  
  120.             cin >> s;  
  121.             len = s.size();  
  122.             hash_s = Hash(s);  
  123.             cin >> n;  
  124.             mxPow = len;  
  125.             for (int i = 0; i < n; i++)  
  126.             {  
  127.                   cin >> p[i];  
  128.                   hash_p[i] = Hash(p[i]);  
  129.                   mxPow = max(mxPow, (int)p[i].size());  
  130.             }  
  131.             for (int i = n; i < n+n; i++)  
  132.             {  
  133.                   p[i] = p[i-n];  
  134.                   reverse(p[i].begin(), p[i].end());  
  135.                   hash_p[i] = Hash(p[i]);  
  136.             }  
  137.             memset(memoize, 0, sizeof memoize);  
  138.             int ans = solve(0);  
  139.             cout << "Set " << tcase << ": ";  
  140.             if (ans > len) cout << "Not possible.\n";  
  141.             else cout << ans << ".\n";  
  142.       }  
  143. }  

No comments:

Post a Comment

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