• UOJ#35 后缀排序


    这是一道模板题。

    读入一个长度为 n 的由小写英文字母组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 1 到 n

    除此之外为了进一步证明你确实有给后缀排序的超能力,请另外输出 n1 个整数分别表示排序后相邻后缀的最长公共前缀的长度。

    输入格式

    一行一个长度为 n 的仅包含小写英文字母的字符串。

    输出格式

    第一行 n 个整数,第 i 个整数表示排名为 i 的后缀的第一个字符在原串中的位置。

    第二行 n1 个整数,第 i 个整数表示排名为 i 和排名为 i+1 的后缀的最长公共前缀的长度。

    样例一

    input

    ababa
    
    

    output

    5 3 1 4 2
    1 3 0 2
    
    

    explanation

    排序后结果为:

    1. a
    2. aba
    3. ababa
    4. ba
    5. baba

    限制与约定

    1n105

    时间限制1s

    空间限制256MB

    我的后缀平衡树终于过了

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<ctime>
    #include<cstring>
    #include<algorithm>
    #define mid l+r>>1
    #define rep(s,t) for(int i=s;i<=t;i++)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    typedef long long ll;
    int h[maxn],ch[maxn][2],c[maxn],tot,rt;
    ll rk[maxn];
    void rebuild(int o,ll l,ll r) {
        if(!o) return;rk[o]=l+r;
        rebuild(ch[o][0],l,mid);rebuild(ch[o][1],mid,r);
    }
    void rotate(int& o,int d,ll l,ll r) {
        int k=ch[o][d^1];ch[o][d^1]=ch[k][d];ch[k][d]=o;o=k;
        rebuild(o,l,r);
    }
    int cmp(int x,int y) {return c[x]<c[y]||(c[x]==c[y]&&rk[x-1]<rk[y-1]);}
    void insert(int& o,ll l,ll r) {
        if(!o) {o=tot;rk[o]=l+r;return;}
        if(cmp(tot,o)) {insert(ch[o][0],l,mid);if(h[ch[o][0]]>h[o]) rotate(o,1,l,r);}
        else {insert(ch[o][1],mid,r);if(h[ch[o][1]]>h[o]) rotate(o,0,l,r);}
    }
    void insert(int x) {
        c[++tot]=x;h[tot]=rand()*rand();
        insert(rt,1,1ll<<61);
    }
    void print(int o) {
        if(!o) return;
        print(ch[o][0]);
        printf("%lld ",rk[o]);
        print(ch[o][1]);
    }
    int n,sa[maxn],rank[maxn],height[maxn];
    int cmp2(int a,int b) {return rk[n-a+1]<rk[n-b+1];}
    char s[maxn];
    int main() {
        srand(time(0));
        scanf("%s",s);n=strlen(s);
        rep(1,n) insert(s[n-i]-'a'+1),sa[i]=i;
        sort(sa+1,sa+n+1,cmp2);
        rep(1,n) rank[sa[i]]=i,printf("%d ",sa[i]);puts("");
        for(int i=1,j,k=0;i<=n;i++) {
            j=sa[rank[i]-1];
            while(s[i+k-1]==s[j+k-1]) k++;
            height[rank[i]]=k?k--:k;
        }
        rep(2,n) printf("%d ",height[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    S2dao 简单Demo(转)
    Iphone SDK textField 打开和关闭键盘
    s2dao 入门知识2
    Eclipse tomcat Web页面调试
    s2dao 入门知识1
    java 面试
    Iphone SDK ActionSheet 在当前窗口弹出时间选择
    杭电2044
    杭电2076
    杭电2077
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4621016.html
Copyright © 2020-2023  润新知