Open OnlyDeniko opened 1 year ago
` inline bool leq(int aq, int aw, int bq, int bw) { return (aq < bq || (aq == bq && aw <= bw)); }
inline bool leq(int aq, int aw, int ae, int bq, int bw, int be) { return (aq < bq || (aq == bq && leq(aw, ae, bw, be))); }
std::vector cc; static inline void radixPass(std::vector& aa, std::vector& bb, std::vector& rr, int NN, int KK) { cc.assign(KK + 1, 0); for (int i = 0; i < NN; ++i) { cc[rr[aa[i]]]++; } for (int i = 0, sum = 0; i <= KK; ++i) { int tt = cc[i]; cc[i] = sum; sum += tt; } for (int i = 0; i < NN; ++i) { bb[cc[rr[aa[i]]]++] = aa[i]; } }
void suffixArray(std::vector& TT, std::vector& SA, int NN, int KK) { int n_zero = (NN + 2) / 3, n_one = (NN + 1) / 3, n_two = NN / 3, n_o_two = n_zero + n_two; std::vector RR(n_o_two + 3); RR[n_o_two] = RR[n_o_two + 1] = RR[n_o_two + 2] = 0; std::vector SAS(n_o_two + 3); SAS[n_o_two] = SAS[n_o_two + 1] = SAS[n_o_two + 2] = 0; std::vector R_zero(n_zero), SA_zero(n_zero); for (int i = 0, j = 0; i < NN + (n_zero - n_one); ++i) { if (i % 3) { RR[j++] = i; } } std::vector T_two(TT.begin() + 2, TT.end()); std::vector T_one(TT.begin() + 1, TT.end()); radixPass(RR, SAS, T_two, n_o_two, KK); radixPass(SAS, RR, T_one, n_o_two, KK); radixPass(RR, SAS, TT, n_o_two, KK); int name = 0, cq = -1, cw = -1, ce = -1; for (int ii = 0; ii < n_o_two; ++ii) { if (TT[SAS[ii]] != cq || TT[SAS[ii] + 1] != cw || TT[SAS[ii] + 2] != ce) { name++; cq = TT[SAS[ii]]; cw = TT[SAS[ii] + 1]; ce = TT[SAS[ii] + 2]; } if (SAS[ii] % 3 == 1) { RR[SAS[ii] / 3] = name; } else { RR[SAS[ii] / 3 + n_zero] = name; } } if (name < n_o_two) { suffixArray(RR, SAS, n_o_two, name); for (int i = 0; i < n_o_two; ++i) { RR[SAS[i]] = i + 1; } } else { for (int i = 0; i < n_o_two; ++i) { SAS[RR[i] - 1] = i; } } for (int i = 0, j = 0; i < n_o_two; ++i) { if (SAS[i] < n_zero) { R_zero[j++] = 3 SAS[i]; } } radixPass(R_zero, SA_zero, TT, n_zero, KK); for (int pp = 0, t = n_zero - n_one, kk = 0; kk < NN; ++kk) { int ii = SAS[t] < n_zero ? SAS[t] 3 + 1 : (SAS[t] - n_zero) 3 + 2; int jj = SA_zero[pp]; if (SAS[t] < n_zero ? leq(TT[ii], RR[SAS[t] + n_zero], TT[jj], RR[jj / 3]) : leq(TT[ii], TT[ii + 1], RR[SAS[t] - n_zero + 1], TT[jj], TT[jj + 1], RR[jj / 3 + n_zero])) { SA[kk] = ii; ++t; if (t == n_o_two) { for (kk++; pp < n_zero; ++pp, ++kk) { SA[kk] = SA_zero[pp]; } } } else { SA[kk] = jj; pp++; if (pp == n_zero) { for (kk++; t < n_o_two; ++t, ++kk) { SA[kk] = SAS[t] < n_zero ? SAS[t] 3 + 1 : (SAS[t] - n_zero) * 3 + 2; } } } } }
void build_lcp(std::vector& TT, std::vector& sa, std::vector& lcp, int NN) { std::vector arr(NN); for (int i = 0; i < NN; ++i) { arr[sa[i]] = i; } lcp.resize(NN);
auto calc = [&](int indexl, int indexr, int pos) -> int { if (indexr == NN) return 0; int ans = pos; indexl = sa[indexl] + pos; indexr = sa[indexr] + pos; while (std::max(indexl, indexr) < NN) { if (TT[indexl] != TT[indexr]) break; ++ans; ++indexl; ++indexr; } return ans; }; lcp[arr[0]] = calc(arr[0], arr[0] + 1, 0); for (int i = 1; i < NN; ++i) { lcp[arr[i]] = calc(arr[i], arr[i] + 1, std::max(0, lcp[arr[i - 1]] - 1)); }
}
void build(std::string& str, std::vector& sa, std::vector& lcp, int KK) { std::vector TT; TT.reserve(str.size()); for (auto& i : str) { if (i >= 'a') { TT.push_back(i - 'a'); } else { TT.push_back(static_cast(i + 26)); } } TT.push_back(0); TT.push_back(0); TT.push_back(0); sa.assign(str.size(), 0); // double tt = clock(); suffixArray(TT, sa, str.size(), KK); // tt = (clock() - tt) / CLOCKS_PER_SEC; // cout << "BUILD SA = " << tt << std::endl; // tt = clock(); build_lcp(TT, sa, lcp, str.size()); // tt = (clock() - tt) / CLOCKS_PER_SEC; // cout << "BUILD LCP = " << tt << std::endl; } `
` inline bool leq(int aq, int aw, int bq, int bw) { return (aq < bq || (aq == bq && aw <= bw)); }
inline bool leq(int aq, int aw, int ae, int bq, int bw, int be) { return (aq < bq || (aq == bq && leq(aw, ae, bw, be))); }
std::vector cc;
static inline void radixPass(std::vector& aa, std::vector& bb, std::vector& rr,
int NN, int KK) {
cc.assign(KK + 1, 0);
for (int i = 0; i < NN; ++i) {
cc[rr[aa[i]]]++;
}
for (int i = 0, sum = 0; i <= KK; ++i) {
int tt = cc[i];
cc[i] = sum;
sum += tt;
}
for (int i = 0; i < NN; ++i) {
bb[cc[rr[aa[i]]]++] = aa[i];
}
}
void suffixArray(std::vector& TT, std::vector& SA, int NN, int KK) {
int n_zero = (NN + 2) / 3, n_one = (NN + 1) / 3, n_two = NN / 3, n_o_two = n_zero + n_two;
std::vector RR(n_o_two + 3);
RR[n_o_two] = RR[n_o_two + 1] = RR[n_o_two + 2] = 0;
std::vector SAS(n_o_two + 3);
SAS[n_o_two] = SAS[n_o_two + 1] = SAS[n_o_two + 2] = 0;
std::vector R_zero(n_zero), SA_zero(n_zero);
for (int i = 0, j = 0; i < NN + (n_zero - n_one); ++i) {
if (i % 3) {
RR[j++] = i;
}
}
std::vector T_two(TT.begin() + 2, TT.end());
std::vector T_one(TT.begin() + 1, TT.end());
radixPass(RR, SAS, T_two, n_o_two, KK);
radixPass(SAS, RR, T_one, n_o_two, KK);
radixPass(RR, SAS, TT, n_o_two, KK);
int name = 0, cq = -1, cw = -1, ce = -1;
for (int ii = 0; ii < n_o_two; ++ii) {
if (TT[SAS[ii]] != cq || TT[SAS[ii] + 1] != cw || TT[SAS[ii] + 2] != ce) {
name++;
cq = TT[SAS[ii]];
cw = TT[SAS[ii] + 1];
ce = TT[SAS[ii] + 2];
}
if (SAS[ii] % 3 == 1) {
RR[SAS[ii] / 3] = name;
} else {
RR[SAS[ii] / 3 + n_zero] = name;
}
}
if (name < n_o_two) {
suffixArray(RR, SAS, n_o_two, name);
for (int i = 0; i < n_o_two; ++i) {
RR[SAS[i]] = i + 1;
}
} else {
for (int i = 0; i < n_o_two; ++i) {
SAS[RR[i] - 1] = i;
}
}
for (int i = 0, j = 0; i < n_o_two; ++i) {
if (SAS[i] < n_zero) {
R_zero[j++] = 3 SAS[i];
}
}
radixPass(R_zero, SA_zero, TT, n_zero, KK);
for (int pp = 0, t = n_zero - n_one, kk = 0; kk < NN; ++kk) {
int ii = SAS[t] < n_zero ? SAS[t] 3 + 1 : (SAS[t] - n_zero) 3 + 2;
int jj = SA_zero[pp];
if (SAS[t] < n_zero ? leq(TT[ii], RR[SAS[t] + n_zero], TT[jj], RR[jj / 3])
: leq(TT[ii], TT[ii + 1], RR[SAS[t] - n_zero + 1], TT[jj], TT[jj + 1],
RR[jj / 3 + n_zero])) {
SA[kk] = ii;
++t;
if (t == n_o_two) {
for (kk++; pp < n_zero; ++pp, ++kk) {
SA[kk] = SA_zero[pp];
}
}
} else {
SA[kk] = jj;
pp++;
if (pp == n_zero) {
for (kk++; t < n_o_two; ++t, ++kk) {
SA[kk] = SAS[t] < n_zero ? SAS[t] 3 + 1 : (SAS[t] - n_zero) * 3 + 2;
}
}
}
}
}
void build_lcp(std::vector& TT, std::vector& sa, std::vector& lcp, int NN) {
std::vector arr(NN);
for (int i = 0; i < NN; ++i) {
arr[sa[i]] = i;
}
lcp.resize(NN);
}
void build(std::string& str, std::vector& sa, std::vector& lcp, int KK) {
std::vector TT;
TT.reserve(str.size());
for (auto& i : str) {
if (i >= 'a') {
TT.push_back(i - 'a');
} else {
TT.push_back(static_cast(i + 26));
}
}
TT.push_back(0);
TT.push_back(0);
TT.push_back(0);
sa.assign(str.size(), 0);
// double tt = clock();
suffixArray(TT, sa, str.size(), KK);
// tt = (clock() - tt) / CLOCKS_PER_SEC;
// cout << "BUILD SA = " << tt << std::endl;
// tt = clock();
build_lcp(TT, sa, lcp, str.size());
// tt = (clock() - tt) / CLOCKS_PER_SEC;
// cout << "BUILD LCP = " << tt << std::endl;
}
`