後綴排序

luogu P3809 爲例

#include <cstdio>
#include <cstring>
#define R register
const int MaxN = 1000010;
int SA[MaxN], Rank[MaxN], Height[MaxN], x[MaxN], sum[MaxN], y[MaxN];
char s[MaxN];
bool cmp(R int i, R int j, R int k){ return x[i] == x[j] && x[i + k] == x[j + k]; } 
int main()
{
    scanf("%s", s + 1);
    R int n = strlen(s + 1), m = 128;
    for(R int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
    for(R int i = 1; i <= m; i++) sum[i] += sum[i - 1];
    for(R int i = n; i; i--) SA[sum[x[i]]--] = i;
    for(R int i = 1; i < n; i <<= 1)
    {
        R int pos = 0; //此時的y是用於計算SA數組的
        for(R int j = n - i + 1; j <= n; j++) y[++pos] = j; //將長度小於2^i的後綴的第二關鍵字爲0,肯定排在前頭,而且按照從前往後的順序
        for(R int j = 1; j <= n; j++) if(SA[j] > i) y[++pos] = SA[j] - i; //這一步其實把第二關鍵字非0的都加入了,SA[j]<=i的數都排在前i個,一定不會作爲其他數的第二關鍵字
        for(R int j = 1; j <= m; j++) sum[j] = 0;
        for(R int j = 1; j <= n; j++) sum[x[j]]++;
        for(R int j = 1; j <= m; j++) sum[j] += sum[j - 1];
        for(R int j = n; j; j--) SA[sum[x[y[j]]]--] = y[j];  //根據第二關鍵字給出的順序,進行第一關鍵字的排序 
        y[SA[1]] = 1; //此時的y是用於計算x數組的,與前面的用途沒有任何關係
        for(R int j = 2; j <= n; j++) y[SA[j]] = y[SA[j - 1]] + !cmp(SA[j], SA[j - 1], i);
        for(R int j = 1; j <= n; x[j] = y[j], j++);
        m = x[SA[n]];
        if(m == n) break;
    }
    for(R int i = 1; i <= n; i++) printf("%d ", SA[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章