对第一个串建SAM在上面跑第二个串,最后每个节点不能包含第三个串即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define rd(s,n) scanf("%s",s+1),n=(int)strlen(s+1)
#define N 120010
#define SIG 26
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
int las,rt,node_cnt,ocr[N],nxt[N];
struct SAM_node{
int ch[SIG],fa,ans,r,val;
}t[N<<1];char a[N],b[N],c[N];
inline int new_sam_node(int v,int x=0)
{ return x=++node_cnt,t[x].val=v,node_cnt; }
inline int extend(int w,int r)
{
int p=las,np=new_sam_node(t[p].val+1);
while(p&&!t[p].ch[w]) t[p].ch[w]=np,p=t[p].fa;
if(!p) t[np].fa=rt;
else{
int q=t[p].ch[w],v=t[p].val+1;
if(t[q].val==v) t[np].fa=q;
else{
int nq=new_sam_node(v);
t[nq].fa=t[q].fa,t[q].fa=t[np].fa=nq;
memcpy(t[nq].ch,t[q].ch,sizeof(t[nq].ch));
while(p&&t[p].ch[w]==q) t[p].ch[w]=nq,p=t[p].fa;
}
}
return t[las=np].r=r;
}
inline int Run_on_SAM(char *s,int n)
{
for(int x=rt,i=1,l=0;i<=n;i++)
{
int c=s[i]-'a';
while(x&&!t[x].ch[c]) l=t[x=t[x].fa].val;
if(x) x=t[x].ch[c],l++;else x=rt;
t[x].ans=max(t[x].ans,l);
}
return 0;
}
inline int get_nxt(char *s,int n)
{
for(int i=2;i<=n;i++)
{
int &j=nxt[i]=nxt[i-1];
while(j&&s[j+1]!=s[i]) j=nxt[j];
if(s[j+1]==s[i]) j++;
}
return 0;
}
inline int KMP(char *s,int n,char *t,int m)
{
for(int i=1,j=0;i<=n;i++)
{
while(j&&t[j+1]!=s[i]) j=nxt[j];
if(t[j+1]==s[i]) j++;
if(j==m) ocr[i-m+1]=1,j=nxt[j];
}
return 0;
}
int main()
{
int n,m,k,ans=0;rd(a,n),rd(b,m),rd(c,k);
las=rt=new_sam_node(0);
for(int i=1;i<=n;i++) extend(a[i]-'a',i);
for(int i=node_cnt;i>1;i--)
if(!t[t[i].fa].r) t[t[i].fa].r=t[i].r;
Run_on_SAM(b,m),get_nxt(c,k),KMP(a,n,c,k);
for(int i=1;i<=n;i++) ocr[i]=(ocr[i]?i:ocr[i-1]);
for(int i=2;i<=node_cnt;i++)
if(t[i].ans<k) ans=max(ans,t[i].ans);
else ans=max(ans,min(t[i].ans,t[i].r-ocr[t[i].r-k+1]));
return !printf("%d\n",ans);
}