Advertisement
Guest User

Untitled

a guest
Dec 8th, 2019
496
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.84 KB | None | 0 0
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <map>
  4. #include <vector>
  5. #include <random>
  6. #include <fstream>
  7. #include <cstdlib>
  8.  
  9. using namespace std;
  10.  
  11. const int NMAX = 5010;
  12. typedef long long i64;
  13.  
  14. vector <int> last_ap[NMAX];
  15. vector<i64> dp[NMAX];
  16.  
  17. struct SuffixArray {
  18.     int n, csz;
  19.     vector<vector<int>> classes;
  20.     vector<int> cnt, order, oldc, newc, left;
  21.     vector<int> str;
  22.  
  23.     SuffixArray(vector<int> s, bool cyclic) :
  24.         n(s.size() + !cyclic), csz(n + 5), cnt(csz),
  25.         order(n), oldc(n), newc(n), left(n), str(s) {
  26.             if (!cyclic) str.push_back(0);
  27.         }
  28.  
  29.     vector<int> Build() {
  30.         for (int i = 0; i < n; ++i) {
  31.             oldc[i] = newc[i] = str[i];
  32.             order[i] = left[i] = i;
  33.         }
  34.  
  35.         for (int step = 1; step <= 2 * n; step *= 2) {
  36.             // Counting sort (can be replaced by sort with left)
  37.             // although not trivial
  38.             fill(cnt.begin(), cnt.end(), 0);
  39.             for (int i = 0; i < n; ++i) ++cnt[oldc[left[i]]];
  40.             for (int i = 1; i < csz; ++i) cnt[i] += cnt[i - 1];
  41.             for (int i = n - 1; i >= 0; --i)
  42.                 order[--cnt[oldc[left[i]]]] = left[i];
  43.  
  44.             newc[order[0]] = 0;
  45.  
  46.             for (int i = 1; i < n; ++i) {
  47.                 int now1 = order[i], last1 = order[i - 1],
  48.                 now2 = (now1 + step / 2) % n,
  49.                 last2 = (last1 + step / 2) % n;
  50.  
  51.                 newc[now1] = newc[last1] + (oldc[now1] != oldc[last1]
  52.                         or oldc[now2] != oldc[last2]);
  53.             }
  54.  
  55.             classes.push_back(newc);
  56.             swap(oldc, newc);
  57.  
  58.             for (int i = 0; i < n; ++i) {
  59.                 left[i] = (order[i] + n - step) % n;
  60.             }
  61.         }
  62.  
  63.         return order;
  64.     }
  65.  
  66.     int Compare(int i, int j, int len) {
  67.         for (int step = 0; len; ++step, len /= 2) {
  68.             if (len % 2 == 0) continue;
  69.  
  70.             int ret = classes[step][i] - classes[step][j];
  71.             if (ret != 0) return ret < 0 ? -1 : 1;
  72.  
  73.             i = (i + (1 << step)) % n;
  74.             j = (j + (1 << step)) % n;
  75.         }
  76.         return 0;
  77.     }
  78.  
  79.     int GetLCP(int i, int j) {
  80.         if (i == j) return str.back() == 0 ? n - i - 1 : n;
  81.         int ans = 0;
  82.         for (int step = classes.size() - 1; step >= 0; --step) {
  83.             if (classes[step][i] == classes[step][j]) {
  84.                 i = (i + (1 << step)) % n;
  85.                 j = (j + (1 << step)) % n;
  86.                 ans += (1 << step);
  87.             }
  88.         }
  89.         return min(ans, n); // if cyclic
  90.     }
  91. };
  92.  
  93. int32_t CLASS[NMAX][NMAX];
  94.  
  95. void test()
  96. {
  97.     int n, Add, Copy, Paste;
  98.     cin >> n >> Add >> Copy >> Paste;
  99.  
  100.  
  101.     map<int, int> rndmap;
  102.     auto norm = [&](int x) {
  103.         if (rndmap.count(x)) return rndmap[x];
  104.         return rndmap[x] = rndmap.size() + 1;
  105.     };
  106.  
  107.     vector<int> v(n);
  108.     for (int i = 0; i < n; ++i) {
  109.         cin >> v[i];
  110.         v[i] = norm(v[i]);
  111.     }
  112.     SuffixArray sa(v, false);
  113.     auto order = sa.Build();
  114.     order.erase(order.begin());
  115.    
  116.     int last = -1;
  117.     for (int i = 0; i < n; ++i) {
  118.         int now = order[i];
  119.         if (last == -1) {
  120.             for (int j = now; j <= n; ++j) {
  121.                 CLASS[now + 1][j + 1] = 1;
  122.             }
  123.         } else {
  124.             int lcp = sa.GetLCP(last, now);
  125.             for (int j = now; j <= n; ++j) {
  126.                 int l = j - now + 1;
  127.                 if (last + l > n) {
  128.                     CLASS[now + 1][j + 1] = i + 1;
  129.                 } else {
  130.                     CLASS[now + 1][j + 1] = CLASS[last + 1][last + l];
  131.                     if (l > lcp) CLASS[now + 1][j + 1] += 1;
  132.                 }
  133.             }
  134.         }
  135.         last = now;
  136.     }
  137.  
  138.     for (int i = 0; i <= n + 2; ++i) {
  139.         last_ap[i].assign(n + 2, -1);
  140.     }
  141.  
  142.     for (int i = 0; i < n + 2; ++i) {
  143.         dp[i].assign(n + 2, 1e18);
  144.     }
  145.     dp[1][0] = 0;
  146.  
  147.     for (int i = 1; i <= n; i++) {
  148.         for (int j = i; j <= n; j++) {
  149.             /// vreau sa obtin o subsecventa
  150.             auto valh = CLASS[i][j];
  151.             int l = (j - i + 1);
  152.             if (last_ap[j - i][valh] != -1) {
  153.                 /// pot sa vin de acolo
  154.                 int former_dr = last_ap[j - i][valh]; /// am dat copy paste ultima data
  155.                                           /// si s-a copat pana la former_i
  156.                 int added = (i - former_dr - 1);
  157.                 dp[i][j] = min(dp[i][j], dp[former_dr - l + 1][former_dr] + Paste +
  158.                                             1LL * added * Add);
  159.                 dp[i][j] = min(dp[i][j], dp[i][i - 1] + Copy + Paste);
  160.             }
  161.         }
  162.  
  163.         for (int j = 1; j <= i; j++) {
  164.             dp[i + 1][i] = min(dp[i + 1][i], Add + dp[j][i - 1]);
  165.             dp[i + 1][i] = min(dp[i + 1][i], dp[j][i]);
  166.         }
  167.  
  168.         for (int j = 1; j <= i; j++)
  169.             dp[j][i] = min(dp[j][i], dp[i + 1][i] + Copy);
  170.  
  171.         for (int st = 1; st <= i; st++) {
  172.             /// adaug in hash secventa (st, i)
  173.             int l = (i - st + 1);
  174.             auto valh = CLASS[st][i];
  175.             last_ap[i - st][valh] = i;
  176.         }
  177.     }
  178.  
  179.     cout << dp[n + 1][n] << '\n';
  180. }
  181.  
  182. int32_t main()
  183. {
  184.  
  185.     int t;
  186.     cin >> t;
  187.  
  188.     for (int i = 1; i <= t; i++) {
  189.         cout << "Case #" << i << ": ";
  190.         test();
  191.     }
  192.  
  193.     return 0;
  194. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement