【模板】后缀自动机 (SAM)

P3804 【模板】后缀自动机 (SAM)

参考: 不同子串个数

d[i]来表示该状态点是否为终止点,最后利用每个点的后缀链接形成一棵树,每个点所表示的最长字符串都是其子树中各节点的最长公共后缀。

// Created by CAD
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
struct state{
    int len,link;
    vector<int> Next;
    state(){Next.resize(26);}
}st[maxn<<1];
int siz=0,last=0;
void init(){
    st[0].len=0;
    st[0].link=-1;
}
int d[maxn<<1];
void extend(int c){
    int cur=++siz;
    d[cur]=1;
    st[cur].len=st[last].len+1;
    int p=last;
    while(~p&&!st[p].Next[c]){
        st[p].Next[c]=cur;
        p=st[p].link;
    }
    if(p==-1) st[cur].link=0;
    else{
        int q=st[p].Next[c];
        if(st[p].len+1==st[q].len) st[cur].link=q;
        else{
            int clone=++siz;
            st[clone].len=st[p].len+1;
            st[clone].Next=st[q].Next;
            st[clone].link=st[q].link;
            while(~p && st[p].Next[c]==q){
                st[p].Next[c]=clone;
                p=st[p].link;
            }
            st[q].link=st[cur].link=clone;
        }
    }
    last=cur;
}
int ans;
vector<int> g[maxn<<1];
void dfs(int u){
    for(auto i:g[u]){
        dfs(i);
        d[u]+=d[i];
    }
    if(d[u]!=1) ans=max(ans,d[u]*st[u].len);
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    init();
    string s;cin>>s;
    for(auto i:s)
        extend(i-'a');
    for(int i=1;i<=siz;++i)
        g[st[i].link].push_back(i);
    dfs(0);
    cout<<ans<<endl;
    return 0;
}
posted @ 2020-07-26 13:58  caoanda  阅读(151)  评论(0编辑  收藏  举报