zoukankan      html  css  js  c++  java
  • [BZOJ1031][JSOI2007]字符加密Cipher

    1031: [JSOI2007]字符加密Cipher

    Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7384  Solved: 3198 [Submit][Status][Discuss]

    Description

      喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考。一天,他突然想出了一种他认为是终极的加密办法
    :把需要加密的信息排成一圈,显然,它们有很多种不同的读法。例如下图,可以读作:

     

    JSOI07 SOI07J OI07JS I07JSO 07JSOI 7JSOI0把它们按照字符串的大小排序:07JSOI 7JSOI0 I07JSO JSOI07
     OI07JS SOI07J读出最后一列字符:I0O7SJ,就是加密后的字符串(其实这个加密手段实在很容易破解,鉴于这是
    突然想出来的,那就^^)。但是,如果想加密的字符串实在太长,你能写一个程序完成这个任务吗?

    Input

      输入文件包含一行,欲加密的字符串。注意字符串的内容不一定是字母、数字,也可以是符号等。

    Output

      输出一行,为加密后的字符串。

    Sample Input

    JSOI07

    Sample Output

    I0O7SJ

    HINT

    对于100%的数据字符串的长度不超过100000。

    把原串$S$复制一遍放在后面变为$SS$,求出$SS$的后缀数组,然后按序输出即可

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 200000 + 10;
    int sa[maxn], rank[maxn], tp[maxn], tax[maxn];
    int n, m;
    char s[maxn];
    inline void Rsort(){
        for(int i = 0; i <= m; i++) tax[i] = 0;
        for(int i = 1; i <= n; i++) tax[rank[tp[i]]]++;
        for(int i = 1; i <= m; i++) tax[i] += tax[i - 1];
        for(int i = n; i; i--) sa[tax[rank[tp[i]]]--] = tp[i];
    }
    bool inline cmp(int *a, int l, int r, int w){
        return a[l] == a[r] && a[l + w] == a[r + w]; 
    }
    void suffix(){
        m = 127;
        for(int i = 1; i <= n; i++){
            rank[i] = s[i];
            tp[i] = i;
        }
        Rsort();
        for(int p, w = 1; p < n; w <<= 1, m = p){
            p = 0;
            for(int i = n - w + 1; i <= n; i++) tp[++p] = i;
            for(int i = 1; i <= n; i++)
                if(sa[i] > w) tp[++p] = sa[i] - w;
            Rsort();
            swap(rank, tp);
            p = rank[sa[1]] = 1;
            for(int i = 2; i <= n; i++)
                rank[sa[i]] = cmp(tp, sa[i], sa[i - 1], w) ? p : ++p;
        }
    }
    int main(){
        scanf("%s", s + 1);
        n = strlen(s + 1);
        for(int i = 1; i <= n; i++)
            s[i + n] = s[i];
        n <<= 1;
        suffix();
        n >>= 1;
        for(int i = 1; i <= (n << 1); i++)
            if(sa[i] <= n) printf("%c", s[sa[i] + n - 1]);
        return 0;
    }
  • 相关阅读:
    10.28MySQL的介绍和安装
    10.24 Event事件,进程池与线程池,协程
    10.23GIL全局解释器锁,多线程作用,死锁,递归锁,信号量
    10.22进程互斥锁,队列,堆栈,线程
    10.21 操作系统发展史,进程
    10.18(粘包问题与解决方法,UDP,socketserver)
    day 67小结
    day 67作业
    day 66 小结
    day 66作业
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7440324.html
Copyright © 2011-2022 走看看