• BZOJ1301 字符加密Cipher (后缀数组)


    题意:

    把所有循环字符串的后缀排名,输出这n<1e5个排名的最后一个字符

    思路:

    将该字符串拼接,按照排名顺序输出后缀开头在前一个字符串的情况中的“最后一个字符”即可

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 2e5+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    char s[maxn];
    int sa[maxn],rk[maxn],height[maxn];
    int y[maxn],x[maxn],c[maxn];
    //x是第i个元素的第一关键字
    //y表示第二关键字排名为i的数,第一关键字的位置
    //c是桶
    int n, m;//m是字符个数
    void getSa(){
        for(int i=1;i<=n;i++)++c[x[i]=s[i]];
        for(int i=2;i<=m;i++)c[i]+=c[i-1];
        for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
        for(int k=1;k<=n;k<<=1){
            int num = 0;
            for(int i=n-k+1;i<=n;i++)y[++num]=i;
            for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
            for(int i=1;i<=m;i++)c[i]=0;
            for(int i=1;i<=n;i++)++c[x[i]];
            for(int i=2;i<=m;i++)c[i]+=c[i-1];
            for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;
            swap(x,y);
            x[sa[1]]=1;
            num=1;
            for(int i=2;i<=n;i++){
                x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
            }
            if(num==n)break;
            m=num;
        }
    }
    void getHeight(){
        int k=0;
        for(int i=1; i<=n; ++i)rk[sa[i]]=i;
        for(int i=1; i<=n; ++i){
            if(rk[i]==1) continue;
            if(k)--k;
            int j=sa[rk[i]-1];
            while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k])++k;
            height[rk[i]]=k;
        }
    }
    int main(){
        scanf("%s",s+1);
        n=strlen(s+1);
        for(int i = 1; i <= n; i++)s[i+n]=s[i];
        n=strlen(s+1);
        m=122;//ascll('z')=122
        getSa();
        getHeight();
        for(int i = 1; i <= n; i++){
            if(sa[i]<=n/2)printf("%c",s[sa[i]+n/2-1]);
        }
        return 0;
    }
    /*
    JSOI07
     */
  • 相关阅读:
    图论————拓扑排序
    状态压缩DP:蒙德里安的梦想
    差分+贪心:IncDec序列
    三目运算符
    贪心+高精度:国王游戏
    图论——最小生成树:Prim算法及优化、Kruskal算法,及时间复杂度比较
    图论——Floyd算法拓展及其动规本质
    图论——最短路:Floyd,Dijkstra,Bellman-Ford,SPFA算法及最小环问题
    贪心+DFS:引水入城
    网站移动版本开发踩坑实录一
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11475660.html
Copyright © 2020-2023  润新知