From f014a0ee6a6a5527e851e7b7e1cd096d688492f0 Mon Sep 17 00:00:00 2001 From: arielherself Date: Tue, 17 Dec 2024 19:02:09 +0800 Subject: [PATCH] Add string/sam.cc --- string/sam.cc | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ template.cc | 2 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 string/sam.cc diff --git a/string/sam.cc b/string/sam.cc new file mode 100644 index 0000000..b6754a7 --- /dev/null +++ b/string/sam.cc @@ -0,0 +1,73 @@ +template +struct SAM { + vector fa, len; + vector cloned; + vector cnt; + vector> ch; + int last; + int tot; + + int create(int _fa, int _len, bool _cloned, array&& _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 + optional find(const basic_string& 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 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]; + } + } +}; diff --git a/template.cc b/template.cc index e98d7c7..35a98ad 100644 --- a/template.cc +++ b/template.cc @@ -173,7 +173,7 @@ template pair istream& operator>>(istream&, pair&); template ostream& operator<<(ostream&, const pair&); template istream& operator>>(istream&, array&);