Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define task "LOGINSTR"
- #include <iostream>
- #include <cstdio>
- #include <vector>
- using namespace std;
- using ll = long long;
- using ld = long double;
- constexpr int N = 1e6 + 5;
- constexpr int Inf = 1e9 + 7;
- void read(int &x)
- {
- x = 0;
- register int c;
- while ((c = getchar()) && (c > '9' || c < '0'))
- ;
- for (; c >= '0' && c <= '9'; c = getchar())
- x = x * 10 + c - '0';
- }
- void read(string &x)
- {
- x.clear();
- register int c;
- while ((c = getchar()) && (c > 'z' || c < 'a'))
- ;
- for (; c >= 'a' && c <= 'z'; c = getchar())
- x.push_back(c);
- }
- template <class T>
- inline void Min(T &x, T y)
- {
- if (x > y)
- x = y;
- }
- struct SegmentTree
- {
- vector<int> st;
- int n;
- SegmentTree(int n = 0)
- {
- this->n = n;
- }
- void Setup(int n)
- {
- this->n = n;
- st.assign(n * 4 + 5, Inf);
- }
- void Update(int id, int l, int r, const int &x, const int &v)
- {
- if (l > x || r < x)
- return;
- if (l == r)
- {
- st[id] = v;
- return;
- }
- Update(id << 1, l, (l + r) / 2, x, v);
- Update(id << 1 | 1, (l + r) / 2 + 1, r, x, v);
- st[id] = min(st[id << 1], st[id << 1 | 1]);
- }
- void Update(int x, int v)
- {
- Update(1, 1, n, x, v);
- }
- int Get(int id, int l, int r, const int &a, const int &b)
- {
- if (l > b || r < a)
- return Inf;
- if (l >= a && r <= b)
- return st[id];
- return min(Get(id << 1, l, (l + r) / 2, a, b), Get(id << 1 | 1, (l + r) / 2 + 1, r, a, b));
- }
- int Get(int l, int r)
- {
- return Get(1, 1, n, l, r);
- }
- } g, h;
- struct Trie
- {
- Trie *child[26];
- int v;
- Trie()
- {
- for (int i = 0; i < 26; ++i)
- child[i] = NULL;
- v = 0;
- }
- } f;
- int n, q, lcp[N], l(0);
- int last[N], sz[N];
- int dp[N];
- string p, s;
- vector<int> a;
- void Add(Trie *a, const string &s)
- {
- int id(0);
- while (true)
- {
- if (id == (int)s.size())
- {
- ++a->v;
- return;
- }
- if (!(a->child[s[id] - 'a']))
- a->child[s[id] - 'a'] = new Trie;
- a = a->child[s[id] - 'a'];
- ++id;
- }
- }
- void dfs(Trie *x)
- {
- while (x->v--)
- {
- ++l;
- for (int j = 0; j < (int)s.size() && j < (int)p.size() && s[j] == p[j]; ++j)
- lcp[l] = j + 1;
- sz[l] = p.size();
- s = p;
- }
- for (int i = 0; i < 26; ++i)
- if (x->child[i])
- {
- p.push_back(i + 'a');
- dfs(x->child[i]);
- p.pop_back();
- }
- }
- void Read()
- {
- read(n), read(q);
- for (int i = 1; i <= n; ++i)
- {
- read(p);
- Add(&f, p);
- }
- g.Setup(n);
- h.Setup(n);
- }
- void Sub_2()
- {
- s = "";
- p = "";
- fill_n(dp, N, Inf);
- dfs(&f);
- for (int j = 1; j <= n; ++j)
- {
- while (!a.empty() && lcp[j] <= lcp[a.back()])
- a.pop_back();
- last[j] = a.empty() ? 0 : a.back() - 1;
- a.emplace_back(j);
- }
- for (int i = 1; i <= q; ++i)
- {
- int ans(Inf);
- dp[0] = Inf;
- for (int j = 1; j <= n; ++j)
- {
- dp[j - 1] = (i == 1 ? 0 : min(dp[last[j]], g.Get(last[j] + 1, j - 1) - 2 * lcp[j]));
- h.Update(j, dp[j - 1] + 2 * sz[j]);
- Min(ans, dp[j - 1] + 2 * sz[j]);
- }
- cout << ans << '\n';
- swap(h, g);
- h.Setup(n);
- }
- }
- int32_t main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- if (fopen(task ".INP", "r"))
- {
- freopen(task ".INP", "r", stdin);
- freopen(task ".OUT", "w", stdout);
- }
- Read();
- Sub_2();
- }
Advertisement
Add Comment
Please, Sign In to add comment