P3804 【模板】后缀自动机

P3804 【模板】后缀自动机

后缀自动机模板

详情可见luogu题解板块

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
ll max(ll a,ll b){return a>b?a:b;}
#define N 2000005
struct Sam{
    int nxt[N][26],fa[N],len[N],siz[N];
    int n,p,q,last,ed,c[N],a[N]; char s[N];//last:自动机的末尾点
    Sam(){ed=1;}
    void init(){
        scanf("%s",s+1); n=strlen(s+1);
        for(int i=1;i<=n;++i) add(s[i]-'a');
    }
    void add(int c){
        p=last; len[last=++ed]=len[p]+1; siz[ed]=1;
        for(;p&&!nxt[p][c];p=fa[p]) nxt[p][c]=ed;
        if(!p){fa[ed]=1; return ;}//case 1
        q=nxt[p][c];
        if(len[q]==len[p]+1){fa[ed]=q; return ;}// case 2
        len[++ed]=len[p]+1;
        memcpy(nxt[ed],nxt[q],sizeof(nxt[q]));
        fa[ed]=fa[q]; fa[q]=fa[ed-1]=ed;
        for(;nxt[p][c]==q;p=fa[p]) nxt[p][c]=ed; // case 3
    }
    void calc(){
        ll ans=0;
        for(int i=1;i<=ed;++i) ++c[len[i]];
        for(int i=1;i<=ed;++i) c[i]+=c[i-1];
        for(int i=1;i<=ed;++i) a[c[len[i]]--]=i;
        for(int i=ed;i;--i){//按len的长度逆序处理(显然len[fa[x]]<len[x])
            siz[fa[a[i]]]+=siz[a[i]];
            if(siz[a[i]]>1) ans=max(ans,1ll*siz[a[i]]*len[a[i]]);
        }printf("%lld",ans);
    }
}sam;
int main(){sam.init(); sam.calc(); return 0;}

 

posted @ 2019-01-04 15:04  kafuuchino  阅读(223)  评论(0编辑  收藏  举报