SPOJ LCS2 - Longest Common Substring II(SAM 求多串最长公共子串)

SPOJ LCS2 - Longest Common Substring II(SAM 求多串最长公共子串)_第1张图片
就是 AcWing 2811. 多串最长公共子串 改变一下输入方式即可。

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10, M = N << 1;
char s[10][N];
int fa[M], ch[M][26], len[M], cnt[M];
int tot = 1, np = 1;
int h[M], e[M], ne[M], idx;
int now[M], ans[M];

void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u) {
	for (int i = h[u]; ~i; i = ne[i]) {
		int j = e[i];
		dfs(j);
		now[u] = max(now[u], now[j]);
	}
}

void extend(int c) {
	int p = np;
	np = ++tot;
	len[np] = len[p] + 1, cnt[np] = 1;
	while (p && !ch[p][c]) {
		ch[p][c] = np;
		p = fa[p];
	}
	if (!p) {
		fa[np] = 1;
	}
	else {
		int q = ch[p][c];
		if (len[q] == len[p] + 1) {
			fa[np] = q;
		}
		else {
			int nq = ++tot;
			len[nq] = len[p] + 1;
			fa[nq] = fa[q], fa[q] = fa[np] = nq;
			while (p && ch[p][c] == q) {
				ch[p][c] = nq;
				p = fa[p];
			}
			memcpy(ch[nq], ch[q], sizeof ch[q]);
		}
	}
}

signed main()
{
	int idx = 0;
	while (~scanf("%s", s[idx]))
	{
		if (idx == 0) {
			for (int i = 0; s[0][i]; ++i) {
				extend(s[0][i] - 'a');
			}
		}
		++idx;
	}

	for (int i = 1; i <= tot; ++i) {
		ans[i] = len[i];
	}
	memset(h, -1, sizeof h);
	for (int i = 2; i <= tot; ++i) {
		add(fa[i], i);
	}
	for (int i = 1; i < idx; ++i) {
		memset(now, 0, sizeof now); 
		int p = 1, t = 0;   
		for (int j = 0; s[i][j]; ++j) {
			while (p > 1 && !ch[p][s[i][j] - 'a']) {    
				p = fa[p];
				t = len[p];
			}
			if (ch[p][s[i][j] - 'a']) p = ch[p][s[i][j] - 'a'], ++t;    
			now[p] = max(now[p], t);
		}
		dfs(1); 
		for (int i = 1; i <= tot; ++i) {
			ans[i] = min(ans[i], now[i]);
		}
	}
	int res = -1;
	for (int i = 1; i <= tot; ++i) {
		res = max(res, ans[i]);
	}
	printf("%d\n", res);

	return 0;
}

你可能感兴趣的:(数据结构,算法)