后缀数组:

1、差异:
卡在两个地方。
1是相等的值可能多算或者漏算。要手模一下。相等的不能简单覆盖,记在一个上面。x==y,idx<idy,L和id不同。y的L应该记为idx+1,
否则会多算,重复。所以单调栈是<=。
2是L,R的计算。(i-id[top])之前写的是i-id+1.
性质:排名为 i, j(i < j) 的后缀的 lcp 为 min{height[k] | i + 1 ≤ k ≤ j}
sigma(leni,j)=(n-1)*(n+1)*n/2. n-1是每一个都被算了n-1次。后面是前缀和。
转换:求lcp。求heigh[i]成为最小值的区间。
    单调栈维护。小难点是相等的值要手模一下。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define F(i,a,b) for(register int i=a;i<=b;++i)
#define forb(i,a,b) for(register int i=a;i>=b;--i)
#define il inline
#define LL long long
#define rg register
#define pf(a) printf("%d ",a)
#define PF(a) printf("%lld ",a)
#define phn puts("")
using namespace std;
int read();
/*
卡在两个地方。
1是相等的值可能多算或者漏算。要手模一下。相等的不能简单覆盖,记在一个上面。x==y,idx<idy,L和id不同。y的L应该记为idx+1,
否则会多算,重复。所以单调栈是<=。
2是L,R的计算。(i-id[top])之前写的是i-id+1.
性质:排名为 i, j(i < j) 的后缀的 lcp 为 min{height[k] | i + 1 ≤ k ≤ j}
sigma(leni,j)=(n-1)*(n+1)*n/2. n-1是每一个都被算了n-1次。后面是前缀和。
转换:求lcp。求heigh[i]成为最小值的区间。
    单调栈维护。小难点是相等的值要手模一下。
*/
#define NX 500010
int n,m;
char str[NX];
int a[NX],sa[NX],height[NX],rk[NX],tax[NX],tp[NX];
void Rsort(){
    F(i,0,m)tax[i]=0;
    F(i,1,n)++tax[rk[tp[i]]];
    F(i,1,m)tax[i]+=tax[i-1];
    forb(i,n,1)sa[tax[rk[tp[i]]]--]=tp[i];
}
int cmp(int *f,int x,int y,int w){return f[x]==f[y]&&f[x+w]==f[y+w];}
void Suffix(){
    F(i,1,n)rk[i]=a[i],tp[i]=i;
    m=127;Rsort();
    for(int w=1,p=1,i;p<n;w<<=1,m=p){
        for(p=0,i=n-w+1;i<=n;++i)tp[++p]=i;
        F(i,1,n)if(sa[i]>w)tp[++p]=sa[i]-w;
        Rsort();swap(rk,tp);rk[sa[1]]=p=1;
        F(i,2,n)rk[sa[i]]=cmp(tp,sa[i],sa[i-1],w)?p:++p;
    }
    int j,k=0;
    for(int i=1;i<=n;height[rk[i++]]=k)
        for(k=k?k-1:k,j=sa[rk[i]-1];a[i+k]==a[j+k];++k);
}
int sta[NX],id[NX],bg[NX],top;
int main(){
    scanf("%s",str+1);
    n=strlen(str+1);
    F(i,1,n)a[i]=str[i];
    Suffix();
    LL ans=1ll*(n-1)*(n+1)*n/2;
  //  F(i,1,n)pf(rk[i]);phn;
  //  F(i,1,n)pf(height[i]);phn;
    height[n+1]=-1;
  //  PF(ans);
    F(i,1,n+1){
        while(top&&sta[top]>height[i]){
            ans-=2ll*(id[top]-bg[top])*(i-id[top])*sta[top--];//PF(ans);
        }
        if(!top){
            sta[++top]=height[i];id[top]=i;bg[top]=0;
        }
        else{
        //    if(sta[top]!=height[i]){
               sta[++top]=height[i];id[top]=i;bg[top]=id[top-1];
        //    }
        }
    }
    printf("%lld",ans);
}
il int read(){
    rg int s=0,f=0;rg char ch;
    while(ch=getchar(),ch=='-'?f=1:0,ch<'0'||ch>'9');
    while(ch>='0'&&ch<='9'){
        s=s*10+(ch^48);ch=getchar();
    }
    return s;
}
/*
g++ 1.cpp -g
./a.out
eededeedeedeedde

*/
View Code
Informatik verbindet dich und mich. 信息将你我连结。
原文地址:https://www.cnblogs.com/seamtn/p/11297648.html