[AHOI2013] 差异 - 后缀数组,单调栈

时间:2019-10-31
本文章向大家介绍[AHOI2013] 差异 - 后缀数组,单调栈,主要包括[AHOI2013] 差异 - 后缀数组,单调栈使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

[AHOI2013] 差异

Description

\(\sum {len(T_i) + len(T_j) - 2 lcp(T_i,T_j)}\) 的值

其中 \(T_i (i = 1,2,...,n)\) 为后缀串 \(S[i,n]\)

Solution

单调栈乱扫一发即可。

始终维护当前栈内元素的和,然后加进答案里。

#include <bits/stdc++.h>
using namespace std;

#define int long long

int n,m=256,sa[1000005],y[1000005],u[1000005],v[1000005],o[1000005],r[1000005],h[1000005],T;
char str[1000005];
int ans = 0, sum = 0;
int sta[1000005],stap[1000005],top=0;

signed main(){
    cin>>str+1;
    n=strlen(str+1);

    for(int i=1;i<=n;i++) u[str[i]]++;
    for(int i=1;i<=m;i++) u[i]+=u[i-1];
    for(int i=n;i>=1;i--) sa[u[str[i]]--]=i;
    r[sa[1]]=1;
    for(int i=2;i<=n;i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);

    for(int l=1;r[sa[n]]<n;l<<=1) {
        memset(u,0,sizeof u);
        memset(v,0,sizeof v);
        memcpy(o,r,sizeof r);
        for(int i=1;i<=n;i++) u[r[i]]++, v[r[i+l]]++;
        for(int i=1;i<=n;i++) u[i]+=u[i-1], v[i]+=v[i-1];
        for(int i=n;i>=1;i--) y[v[r[i+l]]--]=i;
        for(int i=n;i>=1;i--) sa[u[r[y[i]]]--]=y[i];
        r[sa[1]]=1;
        for(int i=2;i<=n;i++) r[sa[i]]=r[sa[i-1]]+((o[sa[i]]!=o[sa[i-1]])||(o[sa[i]+l]!=o[sa[i-1]+l]));
    }
    {
        int i,j,k=0;
        for(int i=1;i<=n;h[r[i++]]=k)
            for(k?k--:0,j=sa[r[i]-1];str[i+k]==str[j+k];k++);
    }
    for(int i=1;i<=n;i++)
    {
        ans += i*(n-1ll);
    }
    for(int i=1;i<=n;i++)
    {
        while(top && sta[top]>=h[i])
        {
            sum -= sta[top] * (stap[top]-stap[top-1]);
            --top;
        }
        ++top;
        sta[top]=h[i];
        stap[top]=i;
        sum += sta[top] * (stap[top]-stap[top-1]);
        //cout<<"i="<<i<<" sum="<<sum<<endl;
        ans -= 2ll*sum;
    }

    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/mollnn/p/11770631.html