P3804 模板后缀自动机

Posted dreagonm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3804 模板后缀自动机相关的知识,希望对你有一定的参考价值。

思路

很水的后缀自动机
找到最长的大小不为1的endpos与maxlen的乘积即可

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 1000100*2;
int trans[MAXN][26],suflink[MAXN],maxlen[MAXN],endpos[MAXN],ispre[MAXN],in[MAXN],n,cnt;
char s[MAXN];
int new_state(int _maxlen,int *_trans,int _suflink){
    ++cnt;
    maxlen[cnt]=_maxlen;
    if(_trans)
        for(int i=0;i<26;i++)
            trans[cnt][i]=_trans[i];
    suflink[cnt]=_suflink;
    return cnt;
}
int add_len(int u,int c){
    int z=new_state(maxlen[u]+1,NULL,0);
    ispre[z]=1;
    while(u&&(!trans[u][c])){
        trans[u][c]=z;
        u=suflink[u];
    }
    if(!u){
        suflink[z]=1;
        return z;
    }
    int v= trans[u][c];
    if(maxlen[v]==maxlen[u]+1){
        suflink[z]=v;
        return z;
    }
    int y=new_state(maxlen[u]+1,trans[v],suflink[v]);
    suflink[v]=suflink[z]=y;
    while(u&&trans[u][c]==v){
        trans[u][c]=y;
        u=suflink[u];
    }
    return z;
}
queue<int> q;
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    int pre=1;
    cnt=1;
    for(int i=1;i<=n;i++)
        pre=add_len(pre,s[i]-'a');
    for(int i=1;i<=cnt;i++)
        in[suflink[i]]++;
    for(int i=1;i<=cnt;i++) 
        if(!in[i])
            q.push(i);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        endpos[x]+=ispre[x];
        endpos[suflink[x]]+=endpos[x];
        in[suflink[x]]--;
        if(!in[suflink[x]])
            q.push(suflink[x]);
    }
    // for(int i=1;i<=cnt;i++)
    //     printf("%d %d!
",endpos[i],maxlen[i]);
    int ans=0;
    for(int i=1;i<=cnt;i++)
        if(endpos[i]>1)
            ans=max(ans,endpos[i]*maxlen[i]);
    printf("%d
",ans);
    return 0;   
}

以上是关于P3804 模板后缀自动机的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P3804 模板后缀自动机

P3804 模板后缀自动机

P3804 后缀自动机模版

模板后缀自动机 (SAM)

洛谷 P3804 后缀自动机

109 后缀自动机(SAM)