题解:
变成了多个串的最长公共子串了。
还是对一个串建后缀自动机。
其它的串放上去跑。
对于每个状态求一个最小值,最后答案求一个最大值就行了。
但是注意在匹配过程中,匹配到一个状态,但是实际上有很多状态也被匹配到了,考虑这种情况一个状态的值需要传递给它的parent。
这个可以全部求出后按Turpo序来搞。
为什么只传给parent是对的呢?
后缀自动机有一个性质:
两个子串的最长公共后缀为它们对应状态的在parent树上的lca。
现在B串在A串上匹配到了一个状态,C串也匹配到了一个状态,如果A、C的每个后缀相同,这样传会在lca处相遇。
反正我是这么理解的,也许parent还有什么更加神奇的理解。
Code:
#include<cstdio>
#include<cstring>
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int N = 2e5 + 5;
struct suffix_automation {
char s[N];
int tot, last, son[N][26], pre[N], step[N];
#define push(v) step[++ tot] = v
void Extend(int c) {
push(step[last] + 1);
int p = last, np = tot;
for(; p && !son[p][c]; p = pre[p]) son[p][c] = np;
if(!p) pre[np] = 1; else {
int q = son[p][c];
if(step[p] + 1 < step[q]) {
push(step[p] + 1); int nq = tot;
memcpy(son[nq], son[q], sizeof son[q]);
pre[nq] = pre[q]; pre[q] = pre[np] = nq;
for(; son[p][c] == q; p = pre[p]) son[p][c] = nq;
} else pre[np] = q;
}
last = np;
}
void Build() {
tot = last = 1;
scanf("%s", s); int n = strlen(s);
fo(i, 0, n - 1) Extend(s[i] - 'a');
}
int r[N], d[N];
void dg(int x) {
fo(i, 1, d[0]) printf("%c", d[i] + 'a');
printf("\n");
fo(i, 0, 25) if(son[x][i]) {
d[++ d[0]] = i;
dg(son[x][i]);
d[0] --;
}
}
void Turpo() {
fo(i, 1, tot) r[pre[i]] ++;
fo(i, 1, tot) if(!r[i]) d[++ d[0]] = i;
for(int st = 1, en = d[0]; st <= en; st ++)
if(!(-- r[pre[d[st]]])) d[++ en] = pre[d[st]];
}
int mi[N], t[N];
void End() {
memset(mi, 127, sizeof(mi));
for(; scanf("%s", s) != EOF;) {
memset(t, 0, sizeof(t));
int x = 1, len = 0;
int n = strlen(s);
fo(i, 0, n - 1) {
int c = s[i] - 'a';
if(son[x][c]) {
x = son[x][c]; len ++;
} else {
while(x && !son[x][c]) x = pre[x];
if(!x) len = 0, x = 1; else len = step[x] + 1, x = son[x][c];
}
t[x] = max(t[x], len);
}
fo(i, 1, tot) if(t[d[i]])
t[pre[d[i]]] = max(t[pre[d[i]]], step[pre[d[i]]]);
fo(i, 1, tot) mi[i] = min(mi[i], t[i]);
}
int ans = 0;
fo(i, 1, tot) ans = max(ans, mi[i]);
printf("%d", ans);
}
} suf;
int main() {
suf.Build();
suf.Turpo();
suf.End();
}