zoukankan      html  css  js  c++  java
  • uoj35 后缀排序

    题目链接:http://uoj.ac/problem/35

    这是一道模板题。

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

    除此之外为了进一步证明你确实有给后缀排序的超能力,请另外输出 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

    限制与约定

    1n10^5

    时间限制1s

    空间限制256MB

    感想:

    对uoj非常的资瓷啊,后缀数组裸题,不懂的自行百度

    献上一个大爷的博客链接:http://blog.csdn.net/shiqi_614/article/details/7982915

    代码

    #include <cstdio>
    #include <cstring>
    using namespace std;
    int i,j,k,n,m,x,y,t,a[200010],b[100010],b1[100010],d[100010],rk[100010],p[100010],h[100010],s1[100010];
    int height[100010],ans1[100010];
    char s[100010];
    struct data{int x,y;}c[100010],e[100010];
    void get_sa(){
        for (i=1;i<=n;i++)b[s[i]-'a']=1;
        for (i=1;i<26;i++)b[i]+=b[i-1];
        for (i=1;i<=n;i++)a[i]=b[s[i]-'a'];
        for (k=1;k<=n;k*=2){
            for (i=1;i<=n;i++)c[i].x=a[i],c[i].y=a[i+k];
            memset(b,0,sizeof b);
            for (i=1;i<=n;i++)b[c[i].y]++;
            for (i=1;i<=n;i++)b[i]+=b[i-1];
            for (i=1;i<=n;i++)d[b[c[i].y]]=i,b[c[i].y]--;
            for (i=1;i<=n;i++)e[i]=c[d[i]];
            for (i=1;i<=n;i++)c[i]=e[i];
            for (i=1;i<=n;i++)p[i]=d[i];
            memset(b,0,sizeof b);
            for (i=1;i<=n;i++)b[c[i].x]++;
            for (i=1;i<=n;i++)b[i]+=b[i-1];
            for (i=n;i>=1;i--)d[b[c[i].x]]=i,b[c[i].x]--;
            for (i=1;i<=n;i++)e[i]=c[d[i]],rk[i]=d[i];
            for (i=1;i<=n;i++)c[i]=e[i];
            s1[1]=1;
            for (i=2;i<=n;i++)if (c[i].x!=c[i-1].x||c[i].y!=c[i-1].y)s1[i]=s1[i-1]+1;else s1[i]=s1[i-1];
            for (i=1;i<=n;i++)a[p[rk[i]]]=s1[i];
        }
        for (i=1;i<=n;i++)rk[a[i]]=i;
        for (i=1;i<=n;i++)printf("%d ",rk[i]);printf("
    ");
    }
    void get_h(){
        int k=0;
        for (int i=1;i<=n;i++){
            if (a[i]==1) h[i]=k=0;
            else{
                j=rk[a[i]-1];
                if (k>0) k--;
                while (i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
                h[i]=k;
            }
            height[a[i]]=h[i];
        }
        for (int i=2; i<=n; i++) printf("%d ",height[i]);
    }
    int main(){
        gets(s);
        n=strlen(s);
        for (i=n;i>=1;i--)s[i]=s[i-1];
        get_sa();
        get_h();
        return 0;
    }
  • 相关阅读:
    POJ 3041 Asteroids 最小点覆盖 == 二分图的最大匹配
    POJ 3083 Children of the Candy Corn bfs和dfs
    POJ 2049 Finding Nemo bfs 建图很难。。
    POJ 2513 Colored Sticks 字典树、并查集、欧拉通路
    POJ 1013 Counterfeit Dollar 集合上的位运算
    POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
    无聊拿socket写的100以内的加法考试。。。
    POJ 1753 Flip Game
    初学socket,c语言写的简单局域网聊天
    汇编语言 复习 第十一章 标志寄存器
  • 原文地址:https://www.cnblogs.com/Acheing/p/6786455.html
Copyright © 2011-2022 走看看