luoguP4248 [AHOI2013]差异

题意

考虑式子前面那段其实是\((n-1)*\frac{n*(n+1)}{2}\),因为每个后缀出现了\(n-1\)次,后缀总长为\(\frac{n*(n+1)}{2}\)

现在考虑后面怎么求:
\(\sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^nlcp(sa_i,sa_j)\)

我们知道后面那个可以转化成\(height\)数组的\(RMQ\)问题,于是我们转而考虑每个\(height_i\)的贡献。

我们对于每个\(i\)找到左边第一个小于\(height_i\)的位置\(j\),右边第一个小于等于\(height_i\)的位置\(k\)(注意条件不同,避免计重),那么\(height_i\)的贡献即为\(height_i*(i-j)*(k-i)\)

这个找的过程显然可以单调栈解决,注意\(height\)\(2\)开始算(因为\([l,r]\)\(height\)\(l+1\)开始,这题所有数据的\(height_1\)都是\(0\),所以能过)。

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=500010;
int n,m,top;
int sa[maxn],rk[maxn],oldrk[maxn],id[maxn],tmpid[maxn],cnt[maxn],height[maxn],sta[maxn],L[maxn],R[maxn];
char s[maxn];
inline bool check(int x,int y,int k){return oldrk[x]==oldrk[y]&&oldrk[x+k]==oldrk[y+k];}
inline void sa_build()
{
    m=300;
    for(int i=1;i<=n;i++)cnt[rk[i]=s[i]]++;
    for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    for(int i=n;i;i--)sa[cnt[rk[i]]--]=i;
    for(int t=1;t<=n;t<<=1)
    {
        int tot=0;
        for(int i=n-t+1;i<=n;i++)id[++tot]=i;
        for(int i=1;i<=n;i++)if(sa[i]>t)id[++tot]=sa[i]-t;
        tot=0;
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++)cnt[tmpid[i]=rk[id[i]]]++;
        for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
        for(int i=n;i;i--)sa[cnt[tmpid[i]]--]=id[i];
        memcpy(oldrk,rk,sizeof(rk));
        for(int i=1;i<=n;i++)rk[sa[i]]=check(sa[i-1],sa[i],t)?tot:++tot;
        m=tot;
        if(m==n)break;
    }
    for(int i=1,j=0;i<=n;i++)
    {
        if(j)j--;
        while(s[i+j]==s[sa[rk[i]-1]+j])j++;
        height[rk[i]]=j;
    }
}
inline ll calc()
{
    ll res=0;
    sta[++top]=1;
    for(int i=2;i<=n;i++)
    {
        while(top&&height[sta[top]]>=height[i])R[sta[top--]]=i;
        L[i]=sta[top];
        sta[++top]=i;
    }
    while(top)R[sta[top--]]=n+1;
    for(int i=2;i<=n;i++)res+=1ll*height[i]*(i-L[i])*(R[i]-i);
    return res;
}
int main()
{
    scanf("%s",s+1);n=strlen(s+1);
    sa_build();
    printf("%lld\n",1ll*(n-1)*n*(n+1)/2-2*calc());
    return 0;
}
posted @ 2019-12-17 08:57  nofind  阅读(107)  评论(0编辑  收藏  举报