Skip to content

Commit 0602978

Browse files
authored
string, SA, cnt sort, pst, djs
1 parent efb9692 commit 0602978

File tree

1 file changed

+211
-0
lines changed

1 file changed

+211
-0
lines changed

Diff for: codeforce/204E.cpp

+211
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
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

Comments
 (0)