BZOJ[3238][Ahoi2013]差异 后缀数组+单调栈

传送门ber~

题目大意:求 1 i < j n l e n ( S u f f i x i ) + l e n ( S u f f i x j ) 2 L C P ( S u f f i x i , S u f f i x j )

l e n ( S u f f i x i ) + l e n ( S u f f i x j ) 可以被提出来
剩下的就是要求 1 i < j n L C P ( S u f f i x i , S u f f i x j )
因为 L C P ( S u f f i x i , S u f f i x j ) 等价于 M i n { H e i g h t i . . . j }
单调栈维护即可

代码如下:

#include<algorithm>
#include<cstring>
#include<cstdio>
#define N 500050
using namespace std;
char str[N];
long long ans;
int n,m,top;
int SA[N],las[N],rk[N],buck[N],height[N],l[N],r[N];
inline bool judge(int x,int y,int k){
    return las[x]==las[y] && las[x+k]==las[y+k];
}
inline void Radix_Sort(){
    for(int i=1;i<=m;i++) buck[i]=0;
    for(int i=1;i<=n;i++) buck[rk[las[i]]]++;
    for(int i=1;i<=m;i++) buck[i]+=buck[i-1];
    for(int i=n;i>=1;i--) SA[buck[rk[las[i]]]--]=las[i];
}
inline void Get_SA(){
    n=strlen(str+1);
    for(int i=1;i<=n;i++){
        las[i]=i;rk[i]=str[i];
    }
    m=127;Radix_Sort();m=0;
    for(int i=1;m<n;i<<=1,top=0){
        for(int j=n-i+1;j<=n;j++) las[++top]=j;
        for(int j=1;j<=n;j++) if(SA[j]>i) las[++top]=SA[j]-i;
        Radix_Sort();m=0;
        for(int j=1;j<=n;j++) las[j]=rk[j];
        for(int j=1;j<=n;j++) rk[SA[j]]=judge(SA[j],SA[j-1],i)?m:++m;
    }
    for(int i=1,j=0;i<=n;i++,j=max(j-1,0)){
        while(str[i+j]==str[SA[rk[i]-1]+j]) j++;
        height[rk[i]]=j;
    }
}
struct sta{
    int x,id;
}s[N];
int main(){
    scanf("%s",str+1);
    Get_SA();
    top=0;
    for(int i=1;i<=n;i++){
        while(top && height[i]<s[top].x)
            r[s[top--].id]=i;
        s[++top].x=height[i];
        s[top].id=i;
    }
    while(top) r[s[top--].id]=n+1;
    for(int i=n;i;i--){
        while(top && height[i]<=s[top].x)
            l[s[top--].id]=i;
        s[++top].x=height[i];
        s[top].id=i;
    }
    while(top) r[s[top--].id]=0;
    ans=1ll*(n+1)*n*(n-1)/2;
    for(int i=1;i<=n;i++) ans=ans-2ll*height[i]*(i-l[i])*(r[i]-i);
    printf("%lld",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/waduan2/article/details/79675886