1
0
Fork 0

Add string/sam.cc

This commit is contained in:
arielherself 2024-12-17 19:02:09 +08:00
parent 53f807d287
commit f014a0ee6a
Signed by: arielherself
SSH Key Fingerprint: SHA256:AK3cyo9tFsp7Mox7K0sYphleC8hReXhnRKxwuDT5LBc
2 changed files with 74 additions and 1 deletions

73
string/sam.cc Normal file
View File

@ -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];
}
}
};

View File

@ -173,7 +173,7 @@ template <typename T, typename Iterator> pair<size_t, unordered_map<T, size_t, s
/* io */ /* io */
#define untie __AS_PROCEDURE(ios_base::sync_with_stdio(0), cin.tie(NULL)) #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> istream& operator>>(istream&, pair<T, U>&);
template<typename T, typename U> ostream& operator<<(ostream&, const 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>&); template<typename T, size_t N> istream& operator>>(istream&, array<T, N>&);