模板 字尾排序(SA陣列)

2022-04-29 22:21:17 字數 1350 閱讀 1951

這是一道模板題。

讀入乙個長度為 \(n\) 的由大小寫英文本母或數字組成的字串,請把這個字串的所有非空字尾按字典序從小到大排序,然後按順序輸出字尾的第乙個字元在原串中的位置。位置編號為 \(1\) 到 \(n\) 。

輸入格式:

一行乙個長度為 \(n\) 的僅包含大小寫英文本母或數字的字串。

輸出格式:

一行,共 \(n\) 個整數,表示答案。

輸入樣例#1:複製

ababa

輸出樣例#1:複製

5 3 1 4 2

\(n <= 10^6\)

num[i]=桶計數

sa[i]=第i個排名的字尾的開頭位置

先來看個圖

接下來看**

void sort()

這時候比較難理解的就是最後一句對吧,別急,看後面的**。

cnt=0;

for(int i=1;i<=w;i++)tp[++cnt]=n-w+i;

for(int i=1;i<=n;i++)if(sa[i]>w)tp[++cnt]=sa[i]-w;

#include#include#include#include#includeusing namespace std;

const int n=1000100;

char s[n];

int sa[n],rak[n],tp[n],num[n];

int n,m=200;

void sort()

void sa_sort()

sort();

int p=0,w=1,cnt;

while(pw)tp[++cnt]=sa[i]-w;

sort();swap(rak,tp);

rak[sa[1]]=p=1;

for(int i=2;i<=n;i++)

if((tp[sa[i]]==tp[sa[i-1]])&&(tp[sa[i]+w]==tp[sa[i-1]+w]))

rak[sa[i]]=p;

else rak[sa[i]]=++p;

w<<=1;m=p;

}}int main()

return 0;

}

P3809 模板 字尾排序 (字尾陣列sa )

題意 讀入乙個長度為 n的由大小寫英文本母或數字組成的字串,請把這個字串的所有非空字尾按字典序從小到大排序,然後按順序輸出字尾的第乙個字元在原串中的位置。位置編號為 1到 n。資料範圍 n 1e6 解法 題目要求的是排名第x的字尾在原串中的位置,其實就是字尾陣列中的sa陣列,算出來直接輸出就行了 c...

SA 字尾陣列

首先一定要確定sa 是個什麼東西 sa i 表示的是排名為 i 的字尾是哪乙個 至於字尾 i的排名是多少,那個是ra nk i 當然啦 最最最難懂的就是基數排序 要是不用基數排序,每次對於乙個二元組直接so rt一下 這樣的複雜度是o nlog 2 對於二元組的基數排序應該是這樣做的 首先把所有元素...

字尾陣列SA

給定乙個字串s,按字典序排序s的所有子串 鬼知道什麼思想,好像沒有什麼思想。哦,想起來了,是倍增。考慮最簡單的字尾間o n o n 比較和快排o nlog n o n logn 總複雜度o n2lo gn o n 2log n 考慮優化字串間的比較,用倍增的思想,假設k 2 k 2 長度的已經比完了...