P3804 【模板】后缀自动机 (SAM) && P6139 【模板】广义后缀自动机(广义 SAM)

普通 \(\text{SAM Code}\)

#include <cstdio>
#include <iostream>
#include <cstring>
#define IN inline
using namespace std;

template <typename T>
IN void read(T &x) {
	x = 0; char ch = getchar(); int f = 0;
	for(; !isdigit(ch); f = (ch == '-' ? 1 : f), ch = getchar());
	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
	if (f) x = ~x + 1;
}

typedef long long LL;
const int N = 2e6 + 5;
int n;
char str[N];
LL ans;

struct SAM {
	int fa[N], len[N], ch[N][26], lst, sz[N], size;
	IN SAM(){size = lst = 1;}
	IN void insert(int c) {
		int p = lst, np = lst = ++size;
		len[np] = len[p] + 1, sz[np] = 1;
		for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
		if (!p) {fa[np] = 1; return;}
		int q = ch[p][c];
		if (len[q] == len[p] + 1) {fa[np] = q; return;}
		int nq = ++size;
		for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
		len[nq] = len[p] + 1, fa[nq] = fa[q], fa[np] = fa[q] = nq;
		for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
	}
	int h[N], tot;
	struct edge{int to, nxt;}e[N];
	IN void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;}
	void buildPT() {
		for(int i = 2; i <= size; i++) add(fa[i], i);
	}
	void dfs(int x) {
		for(int i = h[x]; i; i = e[i].nxt) dfs(e[i].to), sz[x] += sz[e[i].to];
		if (sz[x] > 1) ans = max(ans, (LL)sz[x] * len[x]);
	}
}T;

int main() {
	scanf("%s", str + 1), n = strlen(str + 1);
	for(int i = 1; i <= n; i++) T.insert(str[i] - 'a');
	T.buildPT(), T.dfs(1), printf("%lld\n", ans);
}

广义 \(\text{SAM Code}\)

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#define IN inline
using namespace std;

template <typename T>
IN void read(T &x) {
	x = 0; char ch = getchar(); int f = 0;
	for(; !isdigit(ch); f = (ch == '-' ? 1 : f), ch = getchar());
	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
	if (f) x = ~x + 1;
}

typedef long long LL;
const int N = 2e6 + 5;
int n, id[N];
char str[N];
LL ans;

struct SAM {
	int fa[N], len[N], ch[N][26], size;
	IN SAM(){size = 1;}
	IN void insert(int lst, int c, int now) {
		int p = lst, np = ++size; id[now] = np;
		len[np] = len[p] + 1;
		for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
		if (!p) fa[np] = 1;
		else {
			int q = ch[p][c];
			if (len[q] == len[p] + 1) fa[np] = q;
			else {
				int nq = ++size;
				for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
				len[nq] = len[p] + 1, fa[nq] = fa[q], fa[np] = fa[q] = nq;
				for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
			}
		}
		ans += len[np] - len[fa[np]];
	}
}S;

struct Trie {
	int size = 1, tr[N][26], fa[N];
	IN void insert() {
		int u = 1, m = strlen(str + 1);
		for(int i = 1; i <= m; i++) {
			int c = str[i] - 'a';
			if (!tr[u][c]) tr[u][c] = ++size;
			fa[tr[u][c]] = u, u = tr[u][c];
		}
	}
	queue<int> Q;
	IN void bfs() {
		Q.push(1), id[1] = 1;
		while (!Q.empty()) {
			int now = Q.front(); Q.pop();
			for(int i = 0; i < 26; i++)
				if (tr[now][i]) S.insert(id[now], i, tr[now][i]), Q.push(tr[now][i]);
		}
	}
}T;

int main() {
	read(n);
	for(int i = 1; i <= n; i++) scanf("%s", str + 1), T.insert();
	T.bfs(), printf("%lld\n", ans);
}
posted @ 2022-10-03 12:27  leiyuanze  阅读(32)  评论(0编辑  收藏  举报