【NEW!】[后缀自动机]模板

题目描述

输出在字符串s中出现超过1次的子串长度乘以它的出现次数

分析

容易想到记录节点size值建出Parent树暴力跑DFS统计

#include <iostream>
#include <cstring>
#include <cstdio>
#define rep(i,a,b) for (i=a;i<=b;i++)
const int N=1e6;
using namespace std;
struct Edge {
    int u,v,nx;
}g[4*N];
int cnt,list[2*N];
struct Node {
    int len,link,sz;
    int c[26];
}s[2*N];
int sz,last;
bool b[2*N];
long long ans;

void Extend(char c) {
    int cur=++sz;
    s[cur].len=s[last].len+1;s[cur].sz=1;
    int p;
    for (p=last;p!=-1&&!s[p].c[c-'a'];p=s[p].link)
    s[p].c[c-'a']=cur;
    last=cur;
    if (p==-1) {
        s[cur].link=0; 
        return;
    }
    int q=s[p].c[c-'a'];
    if (s[q].len==s[p].len+1) {
        s[cur].link=q;
        return;
    }
    int clone=++sz;
    s[clone]=s[q];
    s[clone].sz=0;
    s[clone].len=s[p].len+1;
    s[cur].link=s[q].link=clone;
    for (;p!=-1&&s[p].c[c-'a']==q;p=s[p].link) s[p].c[c-'a']=clone;
}

void Dfs(int u) {
    b[u]=1;
    for (int i=list[u];i;i=g[i].nx)
    if (!b[g[i].v]) {
        Dfs(g[i].v);
        s[u].sz+=s[g[i].v].sz;
    }
    if (s[u].sz>1) ans=max(ans,1ll*s[u].sz*s[u].len);
}

int main() {
    string ss;
    int i;
    cin>>ss;
    s[0].link=-1;
    rep(i,0,ss.length()-1) Extend(ss[i]);
    rep(i,1,sz)
    {g[++cnt].u=s[i].link;g[cnt].v=i;g[cnt].nx=list[s[i].link];list[s[i].link]=cnt;}
    Dfs(0);
    printf("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/ssl_qyh0ice/article/details/81046664