• P4248 [AHOI2013]差异 SAM


    题意:

    戳这里

    分析:

    我们观察题面发现这个式子长得很像树上两点间的距离,这就让我们联想到建一颗 (SAM),然后构建出 (parent) 树,原式等价于求 (parent) 树上任意两点间距离的和值

    典型的树上 (dp),我们考虑每一条边的贡献,每一条边对原式的贡献等价于 (经过该边的点对的数目 imes 边的长度)

    所以我们可以推出 (ans=sum (len[i]-len[link[i]])*(n-siz[i])*siz[i])

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
        int read()
        {
            int x=0,f=1;char ch=getchar();
            while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
            while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
            return x*f;
        }
    
        const int maxn = 1e6+5;
        int n;
        long long ans=0;
        char ch[maxn];
    
        struct suffix_automaton
        {
            int cnt,lst;
            int link[maxn],len[maxn],trans[maxn][26],t[maxn],sa[maxn],siz[maxn];
            suffix_automaton(){cnt=lst=1;}
            
            void insert(int x)
            {
                int cur=++cnt,tmp=lst;lst=cnt;
                len[cur]=len[tmp]+1;siz[cur]=1;
                for(;tmp&&!trans[tmp][x];tmp=link[tmp]) trans[tmp][x]=cur;
                if(!tmp)
                {
                    link[cur]=1;
                }
                else
                {
                    int q=trans[tmp][x];
                    if(len[tmp]+1==len[q])
                    {
                        link[cur]=q;
                    }
                    else
                    {
                        int clone=++cnt;
                        len[clone]=len[tmp]+1;
                        link[clone]=link[q];
                        link[q]=link[cur]=clone;
                        for(int i=0;i<26;i++) trans[clone][i]=trans[q][i];
                        for(;tmp&&trans[tmp][x]==q;tmp=link[tmp]) trans[tmp][x]=clone;
                    }
                }
            }
    
            void sort()
            {
                for(int i=1;i<=cnt;i++) t[len[i]]++;
                for(int i=1;i<=cnt;i++) t[i]+=t[i-1];
                for(int i=1;i<=cnt;i++) sa[t[len[i]]--]=i;
                for(int i=cnt;i>=1;i--)
                {
                    int x=sa[i];siz[link[x]]+=siz[x];
                    ans+=1ll*(n-siz[x])*siz[x]*(len[x]-len[link[x]]);
                }
            }
    
        }sam;
    
        void work()
        {
            scanf("%s",ch+1);n=strlen(ch+1);
            for(int i=n;i>=1;i--) sam.insert(ch[i]-'a');
            sam.sort();
            printf("%lld
    ",ans);
        }
    
    
    }
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    加壳技术
    1002 ( A + B Problem II )
    1000 ( A + B Problem )
    1001 ( Sum Problem )
    背单词Delphi版
    覆盖Form.WndProc来响应消息
    覆盖Dispatch响应消息
    美丽人生论坛看贴工具delphi版
    TWebBrowser组件在DELPHI中POST数据和取得网页源文件
    读淘宝商品描述页源码delphi版
  • 原文地址:https://www.cnblogs.com/youth518/p/14204410.html
Copyright © 2020-2023  润新知