BZOJ-3238: [Ahoi2013]差异(Suffix Array + Cartesian Tree)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3238

这是我ORZ了网上的题解才知道的555:

首先做一次后缀数组,求出sa[],height[],然后对于height[2..len(s)]建立Cartesian Tree,那么每个节点对于题目中项lcp()的贡献为(size[left[v]]+1)*(size[right[v]]+1)(很好证明。。。略),然后得出答案。

代码:

速度依旧被虐成渣。。。

b219ebc4b74543a9194daec31c178a82b901146e.jpg.png
#include 
#include 
#include 
 
using namespace std;
 
#define MAXN 500010
#define ll long long 
#define F(t) father[t]
#define L(t) left[t]
#define R(t) right[t]
#define K(t) key[t]
#define S(t) size[t]
#define clear(t) memset(t,0,sizeof(t))
 
int getstring(char *s) {
    int ch,len=0;
    for (ch=getchar();!(ch>='a'&&ch<='z');ch=getchar()) ;
    s[++len]=ch;
    for (ch=getchar();ch>='a'&&ch<='z';ch=getchar()) s[++len]=ch;
    return len;
}
 
char s[MAXN];
int n,height[MAXN],sa[MAXN],rank[MAXN],w[MAXN],r[MAXN],x[MAXN],y[MAXN];
 
void make_sa() {
    int N,b=1,M=n;
    s[sa[0]=0]='$';
    for (int i=0;i++K(i);t=F(t)) ;
        if (t) {
            L(i)=R(t),R(t)=i,F(i)=t;
        } else if (K(roof)>K(i)) L(i)=roof,roof=i; else L(i)=R(roof),R(roof)=i,F(i)=roof;
        t=i;
    }
    dfs(roof);
    for (int i=2;i<=n;i++) {
        ll ret=(S(L(i))+1)*(S(R(i))+1)*K(i)*2;
        rec-=ret;
    }
    return rec;
}
 
int main() {
    n=getstring(s);
    make_sa();
    printf("%lld\n",Solve());
    return 0;
}

你可能感兴趣的:(BZOJ-3238: [Ahoi2013]差异(Suffix Array + Cartesian Tree))