BZOJ 1031: [JSOI2007]字符加密Cipher

二次联通门 : BZOJ 1031: [JSOI2007]字符加密Cipher

 

 

 

 

/*
    BZOJ 1031: [JSOI2007]字符加密Cipher

    把原串复制一遍
    然后求一遍后缀数组即可
*/
#include <cstdio>
#include <cstring>
#define Max 1000008

void read (int &now)
{
    register char word = getchar ();
    for (now = 0; word < '0' || word > '9'; word = getchar ());
    for (; word >= '0' && word <= '9'; now = now * 10 + word - '0');
}

inline void Swap (int *&a, int *&b)
{
    int *now = a;
    a = b; 
    b = now;
}
 
int sa[Max], rank[Max];
int height[Max];

char line[Max];
int str_1[Max], str_2[Max];

int N, M;


void Get_Suffix ()
{
    register int i;
    static int c[Max], *x = str_1, *y = str_2;

    for (i = 0; i < M; c[i ++] = 0);
    for (i = 0; i < N; c[x[i] = line[i]] ++, i ++);
    for (i = 1; i < M; c[i] += c[i - 1], i ++);
    for (i = N - 1; i >= 0; sa[-- c[x[i]]] = i --);
    register int pos;
    pos = 1;
    for (int j = 1; pos < N; j <<= 1, M = pos)
    {
        pos = 0;
        for (i = N - j; i < N; y[pos ++] = i ++);

        for (i = 0; i < N; i ++)
            if (sa[i] >= j)
                y[pos ++] = sa[i] - j;

        for (i = 0; i < M; c[i ++] = 0);
        for (i = 0; i < N; c[x[y[i]]] ++, i ++);
        for (i = 0; i < M; c[i] += c[i - 1], i ++);
        for (i = N - 1; i >= 0; sa[-- c[x[y[i]]]] = y[i --]);
        Swap (x, y);
        pos = 1;
        x[sa[0]] = 0;
        for (i = 1; i < N; i ++)
            x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j] && sa[i - 1] + j < N && sa[i] + j < N) ? pos - 1 : pos ++;
    }
}

int main (int argc, char *argv[])
{
    scanf ("%s", line);
    N = strlen (line);
    M = 256;
       for (int i = 0; i < N; ++ i) line[i + N] = line[i]; 
    line[N << 1] = 0;
       int P = N; N = 2 * N + 1;
    Get_Suffix (); N = P;
    for (int i = 0; i < N * 2 + 1; i ++)
        if (sa[i] < N) printf ("%c", line[N + sa[i] - 1]);

    return 0;
}

 

posted @ 2017-12-28 20:34  ZlycerQan  阅读(181)  评论(0编辑  收藏  举报