|
| 1 | +//category : string, SA, cnt sort, pst, djs |
| 2 | + |
| 3 | +#include <iostream> |
| 4 | +#include <string> |
| 5 | +#include <vector> |
| 6 | +#include <set> |
| 7 | +#include <algorithm> |
| 8 | +#include <memory.h> |
| 9 | +#define ll long long |
| 10 | +#define pii pair<int,int> |
| 11 | +using namespace std; |
| 12 | +const int LEAF = 1 << 18; |
| 13 | +int d; |
| 14 | +int leaf; |
| 15 | +int g[200002]; |
| 16 | +int lcp[200001]; |
| 17 | +ll tmp[200001]; |
| 18 | +int cnt[200001]; |
| 19 | +int s_ix[200001]; |
| 20 | +int p[200001]; |
| 21 | +int low[200001]; |
| 22 | +int high[200001]; |
| 23 | +int a_ix[200001]; |
| 24 | +int nxt[200001]; |
| 25 | +int root[200001]; |
| 26 | +int st[19 * 200001], l[19 * 200001], r[19 * 200001]; |
| 27 | +ll ans[100001]; |
| 28 | +int stamp[200001]; |
| 29 | +bool cmp(int a, int b){ |
| 30 | + if (g[a] != g[b]) return g[a] < g[b]; |
| 31 | + return g[a + d] < g[b + d]; |
| 32 | +} |
| 33 | +void cnt_sort(int len){ |
| 34 | + int i; |
| 35 | + memset(tmp, 0, sizeof(tmp)); |
| 36 | + |
| 37 | + for (i = 0; i < len; i++) |
| 38 | + cnt[g[min(len, s_ix[i] + d)]]++; |
| 39 | + for (i = 1; i < len || i <= 'z';i++) |
| 40 | + cnt[i]+=cnt[i - 1]; |
| 41 | + for (i = len - 1; i >= 0; i--) |
| 42 | + tmp[--cnt[g[min(len, s_ix[i] + d)]]] = s_ix[i]; |
| 43 | + memset(cnt, 0, sizeof(cnt)); |
| 44 | + for (i = 0; i < len; i++) |
| 45 | + cnt[g[tmp[i]]]++; |
| 46 | + for (i = 1; i < len || i <= 'z'; i++) |
| 47 | + cnt[i] += cnt[i - 1]; |
| 48 | + for (i = len - 1; i >= 0; i--) |
| 49 | + s_ix[--cnt[g[tmp[i]]]] = tmp[i]; |
| 50 | + memset(cnt, 0, sizeof(cnt)); |
| 51 | +} |
| 52 | +int make_tree(int pre, int s, int e, int pos, int val){ |
| 53 | + if (e < pos || pos < s) return pre; |
| 54 | + int ix = ++leaf; |
| 55 | + if (e == pos&&s == pos){ |
| 56 | + st[ix] += val; |
| 57 | + } |
| 58 | + else{ |
| 59 | + l[ix] = make_tree(l[pre], s, (s + e) >> 1, pos, val); |
| 60 | + r[ix] = make_tree(r[pre], 1+((s + e) >> 1),e, pos, val); |
| 61 | + st[ix] = st[l[ix]] + st[r[ix]]; |
| 62 | + } |
| 63 | + return ix; |
| 64 | +} |
| 65 | +int query(int ix,int s,int e,int low){ |
| 66 | + if (e <= low) return 0; |
| 67 | + if (low < s) return st[ix]; |
| 68 | + return query(l[ix], s, (s + e) >> 1, low) + query(r[ix], 1+((s + e) >> 1),e, low); |
| 69 | +} |
| 70 | +int find(int a){ |
| 71 | + if (p[a] != a) p[a] = find(p[a]); |
| 72 | + return p[a]; |
| 73 | +} |
| 74 | +void join(int a,int b){ |
| 75 | + a = find(a); |
| 76 | + b = find(b); |
| 77 | + if (a == b) return; |
| 78 | + |
| 79 | + p[b] = a; |
| 80 | + if (low[a] > low[b]) low[a] = low[b]; |
| 81 | + if (high[a] < high[b]) high[a] = high[b]; |
| 82 | +} |
| 83 | +int main(){ |
| 84 | + int i, j,m; |
| 85 | + int n, k; |
| 86 | + int left, right; |
| 87 | + ll sum=0; |
| 88 | + vector<pii > v; |
| 89 | + set<int> histo; |
| 90 | + string s="", a; |
| 91 | + ios::sync_with_stdio(false); |
| 92 | + cin.tie(0); |
| 93 | + cin >> n >> k; |
| 94 | + for (i = 0; i < n; i++){ |
| 95 | + cin >> a; |
| 96 | + s += a+"#"; |
| 97 | + } |
| 98 | + if (k == 1){ |
| 99 | + for (i = 0; i < s.size(); i++){ |
| 100 | + if (s[i] == '#') cout << sum<<" ",cnt[0]=sum=0; |
| 101 | + else sum += (++cnt[0]); |
| 102 | + } |
| 103 | + return 0; |
| 104 | + } |
| 105 | + if (n < k){ |
| 106 | + for (i = 0; i < n; i++) cout << "0" << " "; |
| 107 | + return 0; |
| 108 | + } |
| 109 | + for (i = 0; i < s.size(); i++){ |
| 110 | + s_ix[i] = i; |
| 111 | + g[i] = s[i]; |
| 112 | + p[i] = i; |
| 113 | + low[i] = high[i] = i; |
| 114 | + histo.insert(i); |
| 115 | + } |
| 116 | + histo.insert(i); |
| 117 | + d = 1; |
| 118 | + do{ |
| 119 | + cnt_sort(s.size()); |
| 120 | + tmp[s_ix[0]] = 1; |
| 121 | + for (i = 1; i < s.size(); i++) |
| 122 | + tmp[s_ix[i]] = tmp[s_ix[i - 1]] + cmp(s_ix[i - 1], s_ix[i]); |
| 123 | + for (i = 0; i < s.size(); i++) |
| 124 | + g[i] = tmp[i]; |
| 125 | + d <<= 1; |
| 126 | + } while (s.size() != g[s_ix[s.size() - 1]]); |
| 127 | + for (i = 0; i < s.size(); i++) g[i]--; |
| 128 | + d = 0; |
| 129 | + for (i = 0; i < s.size(); i++){ |
| 130 | + if (g[i] == 0) continue; |
| 131 | + if (s[i] == '#') continue; |
| 132 | + j = s_ix[g[i] - 1]; |
| 133 | + d = max(d - 1, 0); |
| 134 | + while (i + d < s.size() && j + d < s.size() && s[i + d] == s[j + d]&&s[i+d]!='#') |
| 135 | + lcp[g[i]] = ++d; |
| 136 | + if (lcp[g[i]] > 0) v.push_back({lcp[g[i]],g[i]}); |
| 137 | + d = lcp[g[i]] - 1; |
| 138 | + } |
| 139 | + //assign g's party |
| 140 | + sum = 1; |
| 141 | + for (i = 0; i < s.size(); i++){ |
| 142 | + if (s[i] == '#') sum++; |
| 143 | + else a_ix[g[i]] = sum; |
| 144 | + } |
| 145 | + //nxt |
| 146 | + for (i = s.size() - 1; i >= 0; i--){ |
| 147 | + nxt[i] = cnt[a_ix[i]] == 0 ? s.size() + 1 : cnt[a_ix[i]]; |
| 148 | + cnt[a_ix[i]] = i; |
| 149 | + } |
| 150 | + //make tree by g |
| 151 | + sum = 0; |
| 152 | + for (i = 1; i < s.size(); i++){ //lcp[0] is always 0 |
| 153 | + if (s[s_ix[i]] == '#') root[i] = root[i-1]; |
| 154 | + else if (nxt[i] > s.size()){ |
| 155 | + sum++; |
| 156 | + root[i] = make_tree(root[i - 1], 0, LEAF - 1, nxt[i], sum); |
| 157 | + } |
| 158 | + else |
| 159 | + root[i] = make_tree(root[i - 1], 0, LEAF - 1, nxt[i], 1); |
| 160 | + } |
| 161 | + |
| 162 | + |
| 163 | + sort(v.begin(), v.end()); |
| 164 | + i = v.size() - 1; |
| 165 | + sum = 1; |
| 166 | + while (i >= 0){ |
| 167 | + d = v[i].first; |
| 168 | + //cout << v[i].second << endl; |
| 169 | + while (i >= 0 && v[i].first == d){ |
| 170 | + if (lcp[v[i].second] <= lcp[v[i].second + 1]) |
| 171 | + join(v[i].second, v[i].second + 1);// , printf("join%d,%d\n", v[i].second, v[i].second + 1); |
| 172 | + if (lcp[v[i].second] <= lcp[v[i].second - 1]) |
| 173 | + join(v[i].second - 1, v[i].second);// , printf("join%d,%d\n", v[i].second - 1, v[i].second); |
| 174 | + i--; |
| 175 | + } |
| 176 | + j = i+1; |
| 177 | + while (j!=v.size()){ |
| 178 | + m = v.back().second; |
| 179 | + left = low[find(m)]; |
| 180 | + right = high[find(m)]; |
| 181 | + //cout << m << endl; |
| 182 | + //cout <<","<<m<<","<<find(m)<<","<<left<< "," << right << endl; |
| 183 | + v.pop_back(); |
| 184 | + //if (stamp[m] == sum&&stamp[m-1]==sum) continue; |
| 185 | + if (k <= query(root[right], 0, LEAF - 1, right) - query(root[left - 2], 0, LEAF - 1, right)){ |
| 186 | + //cout << query(root[right], 0, LEAF - 1, right) - query(root[left - 2], 0, LEAF - 1, right) << endl; |
| 187 | + |
| 188 | + //cout << query(root[right], 0, LEAF - 1, right) - query(root[left - 2], 0, LEAF - 1, right) << endl; |
| 189 | + |
| 190 | + |
| 191 | + for (auto it = histo.lower_bound(left - 1); *it <= right;){ |
| 192 | + //cout << *it << endl; |
| 193 | + ans[a_ix[*it]] += d; |
| 194 | + histo.erase(it++); |
| 195 | + } |
| 196 | + /*for (m = left-1; m <= right; m++){ |
| 197 | + if (stamp[m] != sum){ |
| 198 | + ans[a_ix[m]]+=d; |
| 199 | + stamp[m] = sum; |
| 200 | + cout << m <<","<<d<< endl; |
| 201 | + } |
| 202 | + }*/ |
| 203 | + } |
| 204 | + } |
| 205 | + |
| 206 | + //sum++; |
| 207 | + } |
| 208 | + |
| 209 | + for (i = 1; i <= n; i++) cout << ans[i] << " "; |
| 210 | + return 0; |
| 211 | +} |
0 commit comments