P3804(子串的长度*其出现的次数 最大的子串 SAM模板)

题目
在这里插入图片描述每一类串出现的次数就是以该类为根的子树中是前缀节点的(差不多为叶子节点 有不同)个数。 这类串在fail树上往下一直走,直到没路,走到的一定是前缀节点,然后所有以该类串为后缀的前缀节点都会被他走到。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
const int N=1e6+5;
struct Edge{int to,nex;}edge[N<<1];
int head[N<<1],tvt;
void add(int from,int to){
    edge[++tvt]=(Edge){to,head[from]};head[from]=tvt;
}
struct node{
    int len,fa,ch[26];
    node(){len=fa=0;m(ch,0);}
}d[N<<1];
int las=1,tot=1;
char s[N];int sz[N<<1];
void update(int c){
    int p=las,np=las=++tot;sz[tot]=1;
    d[np].len=d[p].len+1;
    for(;p&&!d[p].ch[c];p=d[p].fa) d[p].ch[c]=np;
    if(!p) d[np].fa=1;
    else{
        int q=d[p].ch[c];
        if(d[q].len==d[p].len+1) d[np].fa=q;
        else{
            int nq=++tot;d[nq]=d[q];
            d[nq].len=d[p].len+1;
            d[q].fa=d[np].fa=nq;
            for(;p&&d[p].ch[c]==q;p=d[p].fa) d[p].ch[c]=nq;
        }
    }
}
int ans;
void dfs(int x){
    for(int i=head[x];i;i=edge[i].nex){
        int y=edge[i].to;
        dfs(y),sz[x]+=sz[y];
    }
    if(sz[x]!=1) ans=max(ans,sz[x]*d[x].len);
}
int main(){
    scanf("%s",s+1);int len=strlen(s+1);
    for(int i=1;i<=len;++i) update(s[i]-'a');
    for(int i=2;i<=tot;++i) add(d[i].fa,i);
    dfs(1);
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值