#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e6+10;
char s[MAXN],S[MAXN],Z[MAXN];
int n,val[MAXN],ans,tot;
int sum[MAXN],sum2[MAXN];
const int inf=(1<<30);
struct SuffixTree{
int link[MAXN],ch[MAXN][28],now,rem,n;
int start[MAXN],len[MAXN],tail,s[MAXN];
SuffixTree(){tail=now=1;rem=n=0;len[0]=inf;}
inline int build(int a,int b){
link[++tail]=1;
start[tail]=a;len[tail]=b;
return tail;
}
void Extend(int x){
s[++n]=x;++rem;
for(int last=1;rem;){
while(rem>len[ch[now][s[n-rem+1]]])
rem-=len[now=ch[now][s[n-rem+1]]];
int &v=ch[now][s[n-rem+1]];
int c=s[start[v]+rem-1];
if(!v||x==c){
link[last]=now;last=now;
if(!v)v=build(n,inf);
else break;
}
else{
int u=build(start[v],rem-1);
ch[u][c]=v;ch[u][x]=build(n,inf);
start[v]+=rem-1;len[v]-=rem-1;
link[last]=v=u;last=u;
}
if(now==1)--rem;
else now=link[now];
}
}
}T;
void predfs(int u,int dep){
int L=T.start[u];
int R=L+T.len[u]-1;
R=min(R,T.n);
int V=sum[R]-sum[L-1];
int V2=sum2[R]-sum2[L-1];
if(V)val[u]|=1;
if(V2)val[u]|=2;
if(dep>=inf)return;
for(int i=0;i<28;++i){
if(T.ch[u][i]){
predfs(T.ch[u][i],dep+T.len[T.ch[u][i]]);
val[u]|=val[T.ch[u][i]];
}
}
}
void dfs(int u,int dep){
if(dep>=inf)return;
if(val[u]==3)ans=max(ans,dep);
for(int i=0;i<28;++i){
if(T.ch[u][i]){
dfs(T.ch[u][i],T.len[T.ch[u][i]]+dep);
}
}
}
int main(){
scanf("%s",s+1);
scanf("%s",S+1);
int L=strlen(s+1);
s[++L]=26+'a';
for(int i=1;i<=strlen(S+1);++i)s[++L]=S[i];
s[++L]=27+'a';tot=L;
for(int i=1;i<=L;++i)s[i]-='a';
for(int i=1;i<=L;++i)T.Extend(s[i]);
for(int i=1;i<=tot;++i){
sum[i]=sum[i-1]+(T.s[i]==26);
sum2[i]=sum2[i-1]+(T.s[i]==27);
}
predfs(1,0);
dfs(1,0);
printf("%d\n",ans);
return 0;
}
这份代码WA on Test4.但并不知道为啥错……
思路大概是用前缀和来处理了一下分界符,建树之后深搜到深度最大的含有两个分节符的节点,深度即为答案。
(蒟蒻也是第一次知道 SPOJ 原来可以显示多个测试点)大雾