zoukankan      html  css  js  c++  java
  • P4248 [AHOI2013]差异 解题报告

    P4248 [AHOI2013]差异

    题目描述

    给定一个长度为 (n) 的字符串 (S),令 (T_i) 表示它从第 (i) 个字符开始的后缀。求

    [displaystyle sum_{1leqslant i<jleqslant n} ext{len}(T_i)+ ext{len}(T_j)-2 imes ext{lcp}(T_i,T_j) ]

    其中,( ext{len}(a))表示字符串 (a) 的长度,( ext{lcp}(a,b)) 表示字符串 (a) 和字符串 (b) 的最长公共前缀。

    输入输出格式

    输入格式:

    一行,一个字符串 (S)

    输出格式:

    一行,一个整数,表示所求值。

    说明

    对于 (100\%) 的数据,保证 (2leqslant nleqslant 500000),且均为小写字母。


    思路:先用SA求出height数组,然后从最小的开始删并维护联通性,发现用可以用单调栈处理这个过程。

    我人太傻一开始求错了算法迷了好久...


    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    const int N=5e5+10;
    int sa[N],Rank[N],tax[N],sec[N],height[N],sta[N],L[N],R[N],tot,n,m;
    char s[N];
    void Rsort()
    {
        for(int i=1;i<=m;i++) tax[i]=0;
        for(int i=1;i<=n;i++) ++tax[Rank[i]];
        for(int i=2;i<=m;i++) tax[i]+=tax[i-1];
        for(int i=n;i;i--) sa[tax[Rank[sec[i]]]--]=sec[i];
    }
    bool cmp(int x,int y,int l){return sec[x]==sec[y]&&sec[x+l]==sec[y+l];}
    void SuffixSort()
    {
        scanf("%s",s+1);n=strlen(s+1);
        for(int i=1;i<=n;i++) Rank[i]=s[i]+1-'a',sec[i]=i;
        m=26;Rsort();
        for(int p=0,w=1;p<n;w<<=1,m=p)
        {
            p=0;for(int i=n-w+1;i<=n;i++) sec[++p]=i;
            for(int i=1;i<=n;i++) if(sa[i]>w) sec[++p]=sa[i]-w;
            Rsort();std::swap(Rank,sec);
            Rank[sa[1]]=p=1;
            for(int i=2;i<=n;i++) Rank[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
        }
        for(int p=0,i=1;i<=n;height[Rank[i++]-1]=p)
            for(p=p?p-1:p;s[i+p]==s[sa[Rank[i]-1]+p];++p);
    }
    int main()
    {
        SuffixSort();
        for(int i=1;i<n;i++)
        {
            while(tot&&height[sta[tot]]>=height[i]) --tot;
            L[i]=sta[tot]+1;
            sta[++tot]=i;
        }
        sta[tot=0]=n;
        for(int i=n-1;i;i--)
        {
            while(tot&&height[sta[tot]]>height[i]) --tot;
            R[i]=sta[tot]-1;
            sta[++tot]=i;
        }
        ll ans=1ll*(n+1)*(n-1)*n/2;
        for(int i=1;i<n;i++)
            ans-=2ll*(R[i]-i+1)*(i-L[i]+1)*height[i];
        printf("%lld
    ",ans);
        return 0;
    }
    

    2018.12.15

  • 相关阅读:
    利用HttpModule做流量记录
    VS2010 调试出现 asp.net development server 错误
    利用win7自带的虚拟WIFI网卡,与其他设备共享网络
    关于 ASP 中使用 Server.CreateObject("ADODB.Stream") 上传文件报错
    lightweight jobs
    YOLO v3 包括Tiny-Yolo 训练自己的数据集(Pytorch版本)以及模型评价指标的介绍
    Sublime Text3 下载安装与激活使用
    QT中自定义封装控件笔记
    19_7_25-7_27 暑假学校收获
    数字图像处理基础知识2
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10123382.html
Copyright © 2011-2022 走看看