题解:
后缀自动机的例题。
首先要知道一个性质:
一个状态s,所能代表的子串长度是
(stepparentx,stepx]
。
对串A建后缀自动机。
串B在上面跑。
如果x有对应的子节点,那么直接走过去,len ++
如果当前的x状态上没有对应的子节点,那就x = parent[x],直到有对应的子节点或者出了自动机。
出了自动机,len = 0,注意把x赋回root。
没出自动机,因为x的parent所代表的子串的长度一定小于x所代表的子串的长度,所以新的长度是step[x] +1。
Code:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define mem(a) memset(a, 0, sizeof a)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 5e5 + 5;
struct suffix_automation {
char s[N];
int son[N][26], pre[N], step[N], last, tot;
void push(int 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[q] > step[p] + 1) {
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() {
scanf("%s", s);
tot = last = 1;
mem(son); mem(pre); mem(step);
for(int i = 0, E = strlen(s); i < E; i ++) Extend(s[i] - 'a');
}
void G() {
scanf("%s", s); int n = strlen(s);
int x = 1, ans = 0, len = 0;
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 = step[x] + 1, x = son[x][c]; else x = 1, len = 0;
}
ans = max(ans, len);
}
printf("%d", ans);
}
} suf;
int main() {
suf.Build();
suf.G();
}