
就是 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;
}

文章主要介绍了如何通过动态规划和字典树数据结构解决ACWing平台上的2811题,即求解多个字符串之间的最长公共子串。代码中展示了利用字典树进行预处理和优化的过程,以及在处理每个字符串时如何更新最长公共子串的信息。
477

被折叠的 条评论
为什么被折叠?



