【jzoj5315】【NOIP2017提高A組模擬8.19】【小串串】【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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章