剛剛學完回文自動機
來學字尾陣列
一開始思路看得懂
但是**看不懂呀……
一堆神仙**
洛谷p3809
勿謂我,何強過者,炸哉!
我們需要一種新的演算法——字尾陣列
首先,輸入字串
scanf
("%s"
, ch+1)
; n=
strlen
(ch+1)
;
然後,按照題意
suffix_sort
(ch)
;for
(int i=
1; i<=n; i++
)printf
("%d "
,sa[i]
);
主程式就是這麼簡單
int
main()
好了,廢話完了,步入正題
inline
void
suffix_sort
(char ch)
sort()
;for
(int w=
1, p=
0; p
}
你一定看不懂。(除非你學過)
對,你要是光給我這些**
我也看不懂
陣列定義
某巨佬曰:
sa[i]:排名為i的字尾的位置
rak[i]:從第i個位置開始的字尾的排名,下文為了敘述方便,把從第i個位置開始的字尾簡稱為字尾i
tp[i]:基數排序的第二關鍵字,意義與sa一樣,即第二關鍵字排名為i的字尾的位置
tax[i]:i號元素出現了多少次。輔助基數排序
q:排名?
a:就是字典序啦……
而且
還有這個性質
rak[sa[i]
]=i;
sa[rak[i]
]=i;
如何排序
拆開每個字尾
你會發現
一開始這個字尾第乙個值就是這個字尾的起始值
第二個值呢?
其實,我們可以把乙個字尾看成乙個二元組
( ch
[i],
i)(ch[i], i)
(ch[i]
,i)這裡的chch
ch就是字串
對這個二元組進行基數排序
你就會感到快樂
你就會得到排名
倍增既然是倍增,要有倍增的樣子
p.s.倍增的樣子?不就是暴力?
我們在進行第一次排序時
求出了排名
但是這排名有重複
也就是有並列
所以我們要向外擴充套件每個字尾
無法擴充套件的,補0
你已經發現
我們第一次時取每個字尾的開頭
那麼,就產生了許多重複名次
所以,我們可以去對比每個字尾的前(1*2=2)個字元
如果還不行
就對比前(2*2=4)個字元
以此類推
直到排名沒有並列為止
思想就是這樣
不難吧但是
你看看**……
基數排序
你肯定會問:那個sort函式去**了?
它在這裡:
inline
void
sort()
這個tax,就是桶
如果你不了解基數排序
還是baidu一下
你會問,什麼叫:
s a[
tax[
rak[
tp[i
]]]−
−]=t
p[i]
;sa[tax[rak[tp[i]]]--]=tp[i];
sa[tax
[rak
[tp[
i]]]
−−]=
tp[i
];t ax
[rak
[tp[
i]]]
tax[rak[tp[i]]]
tax[ra
k[tp
[i]]
]就表示當第一關鍵字相同時,第二關鍵字較大的這個字尾的排名是什麼
於是,字尾陣列就完了。
其實我覺得字尾陣列難在看**
思想還是比較好接受的
自為風月馬前卒
洛谷
字尾陣列學習筆記
要用好字尾陣列要先理解裡面幾個陣列的概念 sa i 表示字典序第i大的字尾下標 字典序排名依次是1 len stri ng ra nk i 表示下標為i的字尾字典序排名 he ight i 表示sa i 和sa i 1 最長公共字首的長度.乙個性質 lc p su ffix i suff ix j ...
字尾陣列 學習筆記
字尾陣列是處理字串的強有力的工具 在字串處理當中,字尾樹和字尾陣列都是非常有力的工具。其實字尾陣列是字尾樹的乙個非常精巧的替代品,它比字尾樹容易程式設計實現,能夠實現字尾樹的很多功能而時間複雜度也不太遜色,並且,它比字尾樹所占用的空間小很多。可以說,在資訊學競賽中字尾陣列比字尾樹要更為實用。我們定義...
字尾陣列學習筆記
要用好字尾陣列要先理解裡面幾個陣列的概念 sa i 表示字典序第i大的字尾下標 字典序排名依次是1?len string rank i 表示下標為i的字尾字典序排名 height i 表示sa i 和sa i?1 最長公共字首的長度.乙個性質 lcp suffix i suffix j min ra...