VOJ 字元加密Cipher (字尾陣列)
阿新 • • 發佈:2018-12-10
字元加密Cipher
題意
給你一個長度為N的字串,讓你輸出一個字串,要求,這個字串是原字串迴圈(即每次將第一個字元移至最後一個位置),總共會用N個這樣的字串,然後將這些字串按照字典序排列,按照順序每次輸出這些串的最後一個字元,這樣就形成了一個加密過的字串。
資料範圍:
思路
首先,將所有字串排序,我們想到了什麼,字尾陣列啊。字尾陣列不是隻能對對於字尾的一些陣列進行排序嗎?而這裡是要求將所有迴圈字串進行排序,我們可以將原字串在後面複製一份,這樣可以保證所有後綴字串都比我們要求的字串要長。
這樣不會有什麼影響嗎?
我們可以驗證一下,如果字首都相等的話,我們才會需要比較後面一些的字元,而如果字首都相等了,後面的順序其實是無所謂的
程式碼
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
const int MAXN = 2e5 + 10;
using namespace std;
char s[MAXN];
int N, M, rak[MAXN], sa[MAXN], tax[MAXN], tp[MAXN] ,a[MAXN];
void Debug() {
printf("*****************\n");
printf("下標"); for(int i = 1; i <= N; i++) printf("%d ", i); printf("\n");
printf("sa "); for(int i = 1; i <= N; i++) printf("%d ", sa[i]); printf("\n");
printf("rak "); for(int i = 1; i <= N; i++) printf("%d ", rak[i]);printf("\n");
printf("tp "); for(int i = 1; i <= N; i++) printf("%d ", tp[ i]); printf("\n");
}
inline void Qsort() {
for(int i = 0; i <= M; i++) tax[i] = 0;
for(int i = 1; i <= N; i++) tax[rak[i]]++;
for(int i = 1; i <= M; i++) tax[i] += tax[i - 1];
for(int i = N; i >= 1; i--) sa[ tax[rak[tp[i]]]-- ] = tp[i];
}
void SuffixSort() {
M = 0;//可以看情況進行調節,我這裡進行了拉扯
for(int i = 1; i <= N; i++) rak[i] = a[i], tp[i] = i,M = max(M,a[i]);
Qsort();
for(int w = 1, p = 0; p < N; M = p, w <<= 1) {
p = 0;
for(int i = 1; i <= w; i++) tp[++p] = N - w + i;
for(int i = 1; i <= N; i++) if(sa[i] > w) tp[++p] = sa[i] - w;//這兩句是字尾陣列的核心部分,我已經畫圖說明
Qsort();
swap(tp, rak);
rak[sa[1]] = p = 1;
for(int i = 2; i <= N; i++)
rak[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w]) ? p : ++p;
if (p > N) break;
}
}
int main() {
scanf("%s", s + 1);
int len = strlen(s + 1);
N = len*2;
for (int i = 1;i <= len;i ++) s[i+len] = s[i];
for (int i = 1;i <= N;i ++) a[i] = s[i]-' ';
SuffixSort();
for(int i = 1; i <= N; i++)
if (sa[i] <= len)
printf("%c", s[sa[i]+len-1]);
}