Add string/sam.cc
This commit is contained in:
parent
53f807d287
commit
f014a0ee6a
|
@ -0,0 +1,73 @@
|
|||
template <size_t N>
|
||||
struct SAM {
|
||||
vector<int> fa, len;
|
||||
vector<bool> cloned;
|
||||
vector<int> cnt;
|
||||
vector<array<int, N>> ch;
|
||||
int last;
|
||||
int tot;
|
||||
|
||||
int create(int _fa, int _len, bool _cloned, array<int, N>&& _ch) {
|
||||
fa.emplace_back(_fa);
|
||||
len.emplace_back(_len);
|
||||
cloned.emplace_back(_cloned);
|
||||
ch.emplace_back(_ch);
|
||||
return tot++;
|
||||
}
|
||||
|
||||
SAM(void) : fa(2), len(2), cloned(2), ch(2), last(1), tot(2) {}
|
||||
|
||||
void push_back(size_t c) {
|
||||
int p = last;
|
||||
int nw = create(0, len[p] + 1, false, {});
|
||||
|
||||
while (p != 0 and ch[p][c] == 0) {
|
||||
ch[p][c] = nw;
|
||||
p = fa[p];
|
||||
}
|
||||
|
||||
if (p == 0) {
|
||||
fa[nw] = 1;
|
||||
} else {
|
||||
int q = ch[p][c];
|
||||
if (len[q] == len[p] + 1) {
|
||||
fa[nw] = q;
|
||||
} else {
|
||||
int nq = create(fa[q], len[p] + 1, true, array(ch[q]));
|
||||
fa[nw] = fa[q] = nq;
|
||||
while (p != 0 and ch[p][c] == q) {
|
||||
ch[p][c] = nq;
|
||||
p = fa[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last = nw;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
optional<int> find(const basic_string<T>& seq) {
|
||||
int p = 1;
|
||||
for (auto&& c : seq) {
|
||||
if (ch[p][c] == 0) {
|
||||
return nullopt;
|
||||
}
|
||||
p = ch[p][c];
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
// Fill `cnt` with the number of occurrences of each substring.
|
||||
void populate(void) {
|
||||
cnt.assign(tot, 0);
|
||||
vector<int> idx(tot);
|
||||
iota(idx.begin(), idx.end(), 0);
|
||||
sort_by_key(idx.begin(), idx.end(), expr(len[i], auto&& i), greater());
|
||||
for (auto&& v : idx) {
|
||||
if (v > 1 and not cloned[v]) {
|
||||
cnt[v] += 1;
|
||||
}
|
||||
cnt[fa[v]] += cnt[v];
|
||||
}
|
||||
}
|
||||
};
|
|
@ -173,7 +173,7 @@ template <typename T, typename Iterator> pair<size_t, unordered_map<T, size_t, s
|
|||
/* io */
|
||||
#define untie __AS_PROCEDURE(ios_base::sync_with_stdio(0), cin.tie(NULL))
|
||||
|
||||
// add declarations to avoid cyclic dependency
|
||||
// add declarations to avoid circular dependency
|
||||
template<typename T, typename U> istream& operator>>(istream&, pair<T, U>&);
|
||||
template<typename T, typename U> ostream& operator<<(ostream&, const pair<T, U>&);
|
||||
template<typename T, size_t N> istream& operator>>(istream&, array<T, N>&);
|
||||
|
|
Loading…
Reference in New Issue