bzoj4199 [Noi2015]品酒大會 後綴數組+並查集

題目大意:
定義字符串s的兩個子串爲r相似的當起始位置不同的兩個長度爲r子串完全相同。
第一問: 對於每一個r,求出r相似的子串有多少對,0<=r

#include <cstdio>
#include <algorithm>
#include <iostream>
#define N 320000
using namespace std;
typedef long long LL;
const LL INF=0x3f3f3f3f;
inline int Min(int x,int y) { return x<y?x:y; }
inline int Max(int x,int y) { return x>y?x:y; }
inline LL Max(LL x,LL y) { return x>y?x:y; }
int n,tot;
LL cnt[N],tcnt,ans[N],tmax=-INF*INF;
int f[N],mx[N],cm[N],sz[N],a[N],mi[N],ci[N];
int sa[N],rnk[N],h[N],tmp[N],sum[N],X[N],Y[N];
char s[N];
int findie(int c)
{
    if(f[c]!=c) f[c]=findie(f[c]);
    return f[c];
}
void Union(int x,int y)
{
    int t1=findie(x);
    int t2=findie(y);
    if(sz[t2]>sz[t1]) swap(t1,t2);
    tcnt+=1ll*sz[t1]*sz[t2];
    f[t2]=t1; sz[t1]+=sz[t2];

    if(mx[t2]>mx[t1]) cm[t1]=mx[t1],mx[t1]=mx[t2];
    else if(mx[t2]>cm[t1]) cm[t1]=mx[t2];
    if(cm[t2]>cm[t1]) cm[t1]=cm[t2];

    if(mi[t2]<mi[t1]) ci[t1]=mi[t1],mi[t1]=mi[t2];
    else if(mi[t2]<ci[t1]) ci[t1]=mi[t2];
    if(ci[t2]<ci[t1]) ci[t1]=ci[t2];

    tmax=Max(tmax,1ll*mx[t1]*cm[t1]);
    tmax=Max(tmax,1ll*mi[t1]*ci[t1]);
    return;
}
void get_rank()
{
    for(int i=0;i<=127;i++) sum[i]=0;
    for(int i=1;i<=tot;i++) sum[s[i]]++;
    for(int i=1;i<=127;i++) sum[i]+=sum[i-1];
    for(int i=tot;i>=1;i--) tmp[sum[s[i]]--]=i;
    for(int i=1,t=0;i<=tot;i++)
    {
        if(i==1 || s[tmp[i]]!=s[tmp[i-1]]) t++;
        rnk[tmp[i]]=t;
    }
    return;
}
void digit_sort(int key[],int order[])
{
    for(int i=0;i<=tot;i++) sum[i]=0;
    for(int i=1;i<=tot;i++) sum[key[i]]++;
    for(int i=1;i<=tot;i++) sum[i]+=sum[i-1];
    for(int i=tot;i>=1;i--) tmp[sum[key[order[i]]]--]=order[i];
    for(int i=1;i<=tot;i++) order[i]=tmp[i];
}
void get_height()
{
    int j,k;
    for(int i=1;i<=tot;i++)
    {
        if(rnk[i]==1) continue;
        k=Max(h[rnk[i-1]]-1,0);
        j=sa[rnk[i]-1];
        while(s[i+k]==s[j+k]) k++;
        h[rnk[i]]=k;
    }
}
void Suffix_Array()
{
    get_rank();
    for(int j=1;j<=tot;j<<=1)
    {
        for(int i=1;i<=tot;i++)
        {
            sa[i]=i;
            X[i]=rnk[i];
            Y[i]=i+j<=tot?rnk[i+j]:0;
        }
        digit_sort(Y,sa);
        digit_sort(X,sa);
        for(int i=1,t=0;i<=tot;i++)
        {
            if(i==1 || X[sa[i]]!=X[sa[i-1]] || Y[sa[i]]!=Y[sa[i-1]]) t++;
            rnk[sa[i]]=t;
        }
    }
    get_height();
}
bool cmp(int x,int y) { return h[x]>h[y]; }
int main()
{
    scanf("%d",&n); tot=n;
    scanf("%s",s+1);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    Suffix_Array();
    for(int i=1;i<=n;i++)
    {
        f[i]=i; sz[i]=1;
        mx[i]=a[sa[i]]; mi[i]=a[sa[i]];
        cm[i]=-INF; ci[i]=INF;
        tmp[i]=i;
    }
    sort(tmp+2,tmp+n+1,cmp);
    int now=2;
    for(int i=n-1;i>=0;i--)
    {
        while(now<=n && h[tmp[now]]==i)
        {
            Union(tmp[now],tmp[now]-1);
            now++;
        }
        cnt[i]=tcnt;
        ans[i]=tcnt?tmax:0;
    }
    for(int i=0;i<n;i++)
        printf("%lld %lld\n",cnt[i],ans[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章