Skip to content

Commit fef777d

Browse files
committed
Fixed accidental n^2
1 parent fbfa0d7 commit fef777d

File tree

2 files changed

+63
-83
lines changed

2 files changed

+63
-83
lines changed

string/prefix.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ vector<vector<int>> prefix_automata(string s) {
2222

2323
for (int i = 0; i < n; i++) {
2424
for (int c = 0; c < 26; c++) {
25-
int j = i;
26-
while (j and 'a' + c != s[j]) j = pi[j-1];
27-
if ('a' + c == s[j]) j++;
28-
aut[i][c] = j;
25+
if (i > 0 && 'a' + c != s[i])
26+
aut[i][c] = aut[pi[i-1]][c];
27+
else
28+
aut[i][c] = i + ('a' + c == s[i]);
2929
}
3030
}
3131
return aut;
32-
}
32+
}
33+
34+
int main() {}

string/suffix_array.cpp

Lines changed: 56 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,62 @@
11
#include <bits/stdc++.h>
22

3-
#define REP(i, n) for(int i = 0; i < int(n); ++i)
4-
#define REP2(i, ini, fim) for (int i = int(ini); i <= int(fim); ++i)
5-
63
using namespace std;
74

8-
const int maxn = 101010;
9-
10-
namespace sarray
11-
{
12-
string s;
13-
int n, gap;
14-
int sa[maxn], pos[maxn], tmp[maxn], lcp[maxn];
15-
16-
bool suf_comp(int i, int j)
17-
{
18-
if (pos[i] != pos[j]) return pos[i] < pos[j];
19-
20-
i += gap, j += gap;
21-
22-
return (i < n and j < n)? pos[i] < pos[j] : i > j;
23-
}
24-
25-
void build()
26-
{
27-
n = s.size();
28-
29-
REP(i, n) sa[i] = i, pos[i] = s[i];
30-
31-
for (gap=1;; gap <<= 1) {
32-
33-
sort(sa, sa+n, suf_comp);
34-
35-
REP(i, n-1) tmp[i+1] = tmp[i] + suf_comp(sa[i], sa[i+1]);
36-
REP(i, n) pos[sa[i]] = tmp[i];
37-
38-
if (tmp[n-1] == n-1) break;
39-
}
40-
}
41-
42-
void buildLCP()
43-
{
44-
for (int i = 0, k = 0; i < n; ++i) if (pos[i] != n - 1)
45-
{
46-
for (int j = sa[pos[i] + 1]; s[i + k] == s[j + k]; ++k);
47-
lcp[pos[i]] = k;
48-
if (k)--k;
49-
}
50-
}
51-
52-
int ds()
53-
{
54-
int result = n - sa[0];
55-
56-
for (int i = 1; i < n; i++)
57-
result += (n - sa[i]) - lcp[i - 1];
58-
59-
result++;
60-
return result;
61-
}
62-
} // namespace sarray
63-
64-
int main()
65-
{
66-
ios_base::sync_with_stdio(false);
67-
cin.tie(0);
68-
69-
// int t;
70-
// cin >> t;
71-
72-
// while (t--) {
5+
vector<int> sort_cyclic_shifts(string const& s) {
6+
int const n = s.size();
7+
int const alphabet = 256;
8+
vector<int> p(n), c(n), cnt(max(alphabet, n), 0);
9+
10+
for (int i = 0; i < n; i++)
11+
cnt[s[i]]++;
12+
for (int i = 1; i < alphabet; i++)
13+
cnt[i] += cnt[i-1];
14+
for (int i = 0; i < n; i++)
15+
p[--cnt[s[i]]] = i;
16+
17+
c[p[0]] = 0;
18+
int classes = 1;
19+
20+
for (int i = 1; i < n; i++) {
21+
if (s[p[i]] != s[p[i-1]])
22+
classes++;
23+
c[p[i]] = classes - 1;
24+
}
7325

74-
cin >> sarray::s;
75-
76-
sarray::build();
77-
sarray::buildLCP();
78-
REP(i, sarray::n) cout << sarray::lcp[i] << " ";
79-
cout << "\n";
80-
// sarray::buildLCP();
81-
82-
// cout << sarray::ds() << "\n";
83-
// }
26+
vector<int> pn(n), cn(n);
27+
28+
for (int h = 0; (1 << h) < n; ++h) {
29+
for (int i = 0; i < n; i++) {
30+
pn[i] = p[i] - (1 << h);
31+
if (pn[i] < 0)
32+
pn[i] += n;
33+
}
34+
35+
fill(cnt.begin(), cnt.begin() + classes, 0);
36+
for (int i = 0; i < n; i++)
37+
cnt[c[pn[i]]]++;
38+
for (int i = 1; i < classes; i++)
39+
cnt[i] += cnt[i-1];
40+
for (int i = n-1; i >= 0; i--)
41+
p[--cnt[c[pn[i]]]] = pn[i];
42+
cn[p[0]] = 0;
43+
classes = 1;
44+
45+
for (int i = 1; i < n; i++) {
46+
pair<int, int> cur = {c[p[i]], c[(p[i] + (1 << h)) % n]};
47+
pair<int, int> prev = {c[p[i-1]], c[(p[i-1] + (1 << h)) % n]};
48+
if (cur != prev)
49+
++classes;
50+
cn[p[i]] = classes - 1;
51+
}
52+
c.swap(cn);
53+
}
54+
return p;
55+
}
56+
57+
vector<int> suffix_array(string s) {
58+
s += "$";
59+
vector<int> sorted_shifts = sort_cyclic_shifts(s);
60+
sorted_shifts.erase(sorted_shifts.begin());
61+
return sorted_shifts;
8462
}

0 commit comments

Comments
 (0)