Dang_Quan_10_Tin

LOGINSTR_CSP2020

Aug 10th, 2021 (edited)
1,206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.84 KB | None | 0 0
  1. #define task "LOGINSTR"
  2.  
  3. #include <iostream>
  4. #include <cstdio>
  5. #include <vector>
  6.  
  7. using namespace std;
  8.  
  9. using ll = long long;
  10. using ld = long double;
  11.  
  12. constexpr int N = 1e6 + 5;
  13. constexpr int Inf = 1e9 + 7;
  14.  
  15. void read(int &x)
  16. {
  17.     x = 0;
  18.     register int c;
  19.     while ((c = getchar()) && (c > '9' || c < '0'))
  20.         ;
  21.     for (; c >= '0' && c <= '9'; c = getchar())
  22.         x = x * 10 + c - '0';
  23. }
  24.  
  25. void read(string &x)
  26. {
  27.     x.clear();
  28.     register int c;
  29.     while ((c = getchar()) && (c > 'z' || c < 'a'))
  30.         ;
  31.     for (; c >= 'a' && c <= 'z'; c = getchar())
  32.         x.push_back(c);
  33. }
  34.  
  35. template <class T>
  36. inline void Min(T &x, T y)
  37. {
  38.     if (x > y)
  39.         x = y;
  40. }
  41.  
  42. struct SegmentTree
  43. {
  44.     vector<int> st;
  45.     int n;
  46.  
  47.     SegmentTree(int n = 0)
  48.     {
  49.         this->n = n;
  50.     }
  51.  
  52.     void Setup(int n)
  53.     {
  54.         this->n = n;
  55.         st.assign(n * 4 + 5, Inf);
  56.     }
  57.  
  58.     void Update(int id, int l, int r, const int &x, const int &v)
  59.     {
  60.         if (l > x || r < x)
  61.             return;
  62.         if (l == r)
  63.         {
  64.             st[id] = v;
  65.             return;
  66.         }
  67.  
  68.         Update(id << 1, l, (l + r) / 2, x, v);
  69.         Update(id << 1 | 1, (l + r) / 2 + 1, r, x, v);
  70.  
  71.         st[id] = min(st[id << 1], st[id << 1 | 1]);
  72.     }
  73.  
  74.     void Update(int x, int v)
  75.     {
  76.         Update(1, 1, n, x, v);
  77.     }
  78.  
  79.     int Get(int id, int l, int r, const int &a, const int &b)
  80.     {
  81.         if (l > b || r < a)
  82.             return Inf;
  83.         if (l >= a && r <= b)
  84.             return st[id];
  85.  
  86.         return min(Get(id << 1, l, (l + r) / 2, a, b), Get(id << 1 | 1, (l + r) / 2 + 1, r, a, b));
  87.     }
  88.  
  89.     int Get(int l, int r)
  90.     {
  91.         return Get(1, 1, n, l, r);
  92.     }
  93. } g, h;
  94. struct Trie
  95. {
  96.     Trie *child[26];
  97.     int v;
  98.     Trie()
  99.     {
  100.         for (int i = 0; i < 26; ++i)
  101.             child[i] = NULL;
  102.         v = 0;
  103.     }
  104. } f;
  105.  
  106. int n, q, lcp[N], l(0);
  107. int last[N], sz[N];
  108. int dp[N];
  109. string p, s;
  110. vector<int> a;
  111.  
  112. void Add(Trie *a, const string &s)
  113. {
  114.     int id(0);
  115.     while (true)
  116.     {
  117.         if (id == (int)s.size())
  118.         {
  119.             ++a->v;
  120.             return;
  121.         }
  122.  
  123.         if (!(a->child[s[id] - 'a']))
  124.             a->child[s[id] - 'a'] = new Trie;
  125.  
  126.         a = a->child[s[id] - 'a'];
  127.         ++id;
  128.     }
  129. }
  130.  
  131. void dfs(Trie *x)
  132. {
  133.     while (x->v--)
  134.     {
  135.         ++l;
  136.  
  137.         for (int j = 0; j < (int)s.size() && j < (int)p.size() && s[j] == p[j]; ++j)
  138.             lcp[l] = j + 1;
  139.  
  140.         sz[l] = p.size();
  141.  
  142.         s = p;
  143.     }
  144.  
  145.     for (int i = 0; i < 26; ++i)
  146.         if (x->child[i])
  147.         {
  148.             p.push_back(i + 'a');
  149.             dfs(x->child[i]);
  150.             p.pop_back();
  151.         }
  152. }
  153.  
  154. void Read()
  155. {
  156.     read(n), read(q);
  157.  
  158.     for (int i = 1; i <= n; ++i)
  159.     {
  160.         read(p);
  161.         Add(&f, p);
  162.     }
  163.     g.Setup(n);
  164.     h.Setup(n);
  165. }
  166.  
  167. void Sub_2()
  168. {
  169.     s = "";
  170.     p = "";
  171.  
  172.     fill_n(dp, N, Inf);
  173.  
  174.     dfs(&f);
  175.  
  176.     for (int j = 1; j <= n; ++j)
  177.     {
  178.         while (!a.empty() && lcp[j] <= lcp[a.back()])
  179.             a.pop_back();
  180.         last[j] = a.empty() ? 0 : a.back() - 1;
  181.         a.emplace_back(j);
  182.     }
  183.  
  184.     for (int i = 1; i <= q; ++i)
  185.     {
  186.         int ans(Inf);
  187.  
  188.         dp[0] = Inf;
  189.  
  190.         for (int j = 1; j <= n; ++j)
  191.         {
  192.             dp[j - 1] = (i == 1 ? 0 : min(dp[last[j]], g.Get(last[j] + 1, j - 1) - 2 * lcp[j]));
  193.  
  194.             h.Update(j, dp[j - 1] + 2 * sz[j]);
  195.             Min(ans, dp[j - 1] + 2 * sz[j]);
  196.         }
  197.         cout << ans << '\n';
  198.  
  199.         swap(h, g);
  200.         h.Setup(n);
  201.     }
  202. }
  203.  
  204. int32_t main()
  205. {
  206.     ios::sync_with_stdio(0);
  207.     cin.tie(0);
  208.     cout.tie(0);
  209.     if (fopen(task ".INP", "r"))
  210.     {
  211.         freopen(task ".INP", "r", stdin);
  212.         freopen(task ".OUT", "w", stdout);
  213.     }
  214.     Read();
  215.     Sub_2();
  216. }
  217.  
Advertisement
Add Comment
Please, Sign In to add comment