bzoj 3796 Mushroom追妹纸 - 后缀自动机

对第一个串建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);
}


猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/81380533
今日推荐