1692: [Usaco2007 Dec]队列变换

本文介绍了一种使用后缀数组和贪心策略解决字符串处理问题的方法。通过构建后缀数组并利用贪心思想来确保算法的正确性,文章详细展示了如何实现这一过程,并附带完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

贪心,后缀数组保证正确性

#include<bits/stdc++.h>
#define rep2(i,k,n) for(int i=k;i>=(n);i--)
#define rep(i,k,n) for(int i=k;i<(n);i++)
using namespace std;
const int maxn=100000;
int n;
char read(){char c=getchar();while(c<'A' || c>'Z')c=getchar();return c;}
char s[maxn],s2[maxn];int p1[maxn],p2[maxn],sa[maxn],rank[maxn],c[maxn],sim,h[maxn];
void build_sa(){
    int*x=p1;int*y=p2;
    rep(i,0,n)c[x[i]=s[i]]++;
    rep(i,1,sim)c[i]+=c[i-1];
    rep2(i,n-1,0)sa[--c[x[i]]]=i;
    for(int h=1;h<=n;h<<=1){int t=0;
        rep(i,n-h,n)y[t++]=i;rep(i,0,n)if(sa[i]>=h)y[t++]=sa[i]-h;
        rep(i,0,sim)c[i]=0;
        rep(i,0,n)c[x[y[i]]]++;
        rep(i,1,sim)c[i]+=c[i-1];
        rep2(i,n-1,0)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);t=0;
        x[sa[0]]=0;
        rep(i,1,n)x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+h]==y[sa[i-1]+h] ? t : ++t;
        t++;if(t>=n)break;
        sim=t;
    }
}
void geth(){
    rep(i,0,n)rank[sa[i]]=i;
    int k=0;
    rep(i,0,n){if(!rank[i])continue;
    if(k)k--;
        int j=sa[rank[i]-1];
        while(s[i+k]==s[j+k])k++;
        h[rank[i]]=k;
    }
}
int main(){//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
    scanf("%d",&n);int cn=n;
    rep(i,0,n)s[i]=s[2*n-i]=read();s[n]=0;n=n<<1|1;sim=233;
    build_sa();
    geth();
    int l=0,r=cn-1,t=0;
    while(l<=r){
        s2[t++]=rank[l] > rank[n-r-1] ? s[r--] : s[l++]; 
    }
    rep(i,0,t){
        putchar(s2[i]);if(!((i+1)%80))printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值