【jzoj5315】【NOIP2017提高A组模拟8.19】【小串串】【sam 】

本文深入探讨了SAM算法的具体实现过程,包括构建SAM树、求解失败树的子树大小及其应用。通过具体代码示例,详细解释了如何计算特定贡献值,并提供了一种高效的算法解决方案。

description

这里写图片描述

solution

构出sam,求出fail树子树大小,贡献为size[x]^2*(mx[fa[x]]-mx[x])。

code

#include<set>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
#define ULL unsigned long long
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define fr(i,j) for(int i=begin[j];i;i=next[i])
using namespace std;
int const mn=1e5+9,mp=2*1e5+9,mo=1e9+7;
int t,n,f[mp],mx[mp],fa[mp],son[mp][26],a[mp];
char s[mn];
bool cmp(int x,int y){
    return mx[x]<mx[y];
}
int main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    scanf("%d",&t);
    fo(cas,1,t){
        scanf("%s",s+1);
        n=strlen(s+1);
        fo(i,1,n)s[i]-='a';
        int pon=1,last=1;
        fo(ii,1,n){
            int p=last,np=last=++pon,ch=s[ii];
            mx[np]=mx[p]+1;f[np]=1;
            for(;p&&(!son[p][ch]);p=fa[p])son[p][ch]=np;
            if(!p){fa[np]=1;continue;}
            int q=son[p][ch];
            if(mx[p]+1==mx[q])fa[np]=q;
            else{
                int nq=++pon;
                mx[nq]=mx[p]+1;
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                fo(i,0,25)son[nq][i]=son[q][i];
                for(;p&&(son[p][ch]==q);p=fa[p])son[p][ch]=nq;
            }
        }
        fo(i,1,pon)a[i]=i;
        sort(a+1,a+pon+1,cmp);
        LL ans=0;
        fd(i,pon,2){
            int p=a[i];
            f[fa[p]]+=f[p];
            ans+=1ll*(mx[p]-mx[fa[p]])*f[p]*f[p];
        }
        printf("%lld\n",ans);
        fo(i,1,pon){
            mx[i]=fa[i]=f[i]=0;
            fo(j,0,25)son[i][j]=0;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值