P3809 【模板】後綴排序

學完後綴數組後第一個模板題

後綴中:

sa[i]  : 開頭爲i的後綴

rak[i]:排名爲i的後綴的開頭位置

#include<cstdio>
#include<cstring>
#include<algorithm>
const int MAXN = 1e6 + 10;
using namespace std;
char s[MAXN];
int N, M, rak[MAXN], sa[MAXN], tax[MAXN], tp[MAXN];
//tp[i]   第二關鍵字排名i的下標
//rak[i]  第一關鍵字排名i的下標。。最終是排名i的後綴的下標
//sa[i]   下標i的後綴的排名 
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");
}
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];
    //基數排序,sa[tax[z]--]=tp[i],更新排名
	//z是第二關鍵字排名i的後綴	放在什麼位置。  tax[z]是第一關鍵字排名一樣的放在一起 
}
void SuffixSort() {
    M = 75;
    for (int i = 1; i <= N; i++) rak[i] = s[i] - '0' + 1, tp[i] = i;
    Qsort();
  //  Debug();
    for (int w = 1, p = 0; p < N; M = p, w <<= 1) {
        //w:當前倍增的長度,w = x表示已經求出了長度爲x的後綴的排名,現在要更新長度爲2x的後綴的排名
        //p表示不同的後綴的個數,很顯然原字符串的後綴都是不同的,因此p = N時可以退出循環
        p = 0;//這裏的p僅僅是一個計數器000
        for (int i = N; i >= N-w+1; i--) tp[++p] = i;
//這裏一直沒看懂,其實就是後面的字符串後W是空的  所以優先級更高而已。 
        for (int i = 1; i <= N; i++) if (sa[i] > w) tp[++p] = sa[i] - w; 
//這裏就是利用上一次求的長度w後綴的排名,這次的tp是後w,即i+w位置的rak所以從排名前的往後找,找的優先級一定更高 
     /*   puts("-----"); 
        puts("-----"); 
		Debug();
        puts("-----"); 
        puts("-----"); */
		Qsort();//此時我們已經更新出了第二關鍵字,利用上一輪的rak更新本輪的sa
        swap(tp, rak);//這裏原本tp已經沒有用了
        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;
        //判斷合併後的後綴的前綴是否完全相同。相同就在rak裏相同 
	  //  Debug();
    }
    for (int i = 1; i <= N; i++)
        printf("%d ", sa[i]);
}
int main() {
    scanf("%s", s + 1);
    N = strlen(s + 1);
    SuffixSort();
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章