zoukankan      html  css  js  c++  java
  • 【模板】BZOJ 1692:队列变换—后缀数组 Suffix Array

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1692

    题意:

    给出一个长度为N的字符串,每次可以从串头或串尾取一个字符,添加到新串中,使新串的字典序最小。

    做法:

    经过推导(略),发现只要贪心地取两端字典序较小的一端,所以在一开始对所有的正反后缀排序,即把原串倒过来接在后面求一遍SA就行了。

    写了个倍增求SA[]+height[]的板子,代码可能比较长,但相对来说可能容易理解一点...

    #include <bits/stdc++.h>
    #define TR(x) cout<<#x<<'='<<x<<endl
    using namespace std;
    typedef long long ll;
    const int MAXN=100005;
    int M, N, w[MAXN], ht[MAXN], rk[MAXN], sa[MAXN], c[MAXN];
    char ch[MAXN], ans[MAXN];
    void rsort(int *x, int *y, int up){
    	for(int i=0; i<up; ++i) c[i]=0;
    	for(int i=0; i<N; ++i) c[x[i]]++;
    	for(int i=1; i<up; ++i) c[i]+=c[i-1];
    	for(int i=N-1; i>=0; --i) sa[--c[x[y[i]]]]=y[i];
    }
    inline int cmp(int *x, int a, int b, int k){return x[a]==x[b]&&x[a+k]==x[b+k];}
    void getsa(){
    	int *x=ht, *y=rk, up=30;
    	for(int i=0; i<N; ++i) x[i]=w[i], y[i]=i;
    	rsort(x,y,up);
    	for(int k=1, p; p<N; k<<=1, up=p){
    		p=0;
    		for(int i=N-k; i<N; ++i) y[p++]=i;
    		for(int i=0; i<N; ++i) if(sa[i]>=k) y[p++]=sa[i]-k;
    		rsort(x,y,up); swap(x,y); p=1; x[sa[0]]=0;
    		for(int i=1; i<N; ++i)
    			if(cmp(y,sa[i],sa[i-1],k)) x[sa[i]]=p-1;
    			else x[sa[i]]=p++;
    	}
    	for(int i=0; i<N; ++i) rk[sa[i]]=i;
    	ht[0]=0;
    	for(int i=0, j, p=0; i<N-1; ++i){
    		for((p?p--:0),j=sa[rk[i]-1];w[i+p]==w[j+p];++p);
    		ht[rk[i]]=p-1;
    	}
    }
    int main(){
    	freopen("in.txt", "r", stdin);
    //	freopen("out.txt", "w", stdout);
    	scanf("%d", &M);
    	for(int i=0; i<M; ++i) getchar(), ch[i]=getchar();
    	for(int i=0; i<M; ++i) w[M*2-i]=w[i]=ch[i]-'A'+1;
    	w[M]=27; N=M*2+2;
    	getsa(); fflush(stdout);
    	for(int i=0, j=M-1, t=0; i<=j; t++){
    		if(rk[i]<rk[N-2-j]) ans[t]=ch[i++];
    		else ans[t]=ch[j--];
    	}
    	for(int i=0; i<M; ++i){
    		putchar(ans[i]);
    		if((i+1)%80==0) putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    PAT 甲级 1132 Cut Integer (20 分)
    AcWing 7.混合背包问题
    AcWing 9. 分组背包问题
    AcWing 5. 多重背包问题 II
    AcWing 3. 完全背包问题
    AcWing 4. 多重背包问题
    AcWing 2. 01背包问题
    AcWing 875. 快速幂
    AcWing 874. 筛法求欧拉函数
    AcWing 873. 欧拉函数
  • 原文地址:https://www.cnblogs.com/will7101/p/6627814.html
Copyright © 2011-2022 走看看