字尾陣列小結

2021-08-14 22:14:58 字數 2886 閱讀 3572

一道模板題

字尾陣列(sa)是乙個比較強大的處理字串的演算法,是有關字串的比較基礎是嗎?演算法,所以必須掌握

實現主要有倍增和dc

3 ,而我太弱了只學了倍增

s :就是這個字串,長度為le

nran

k[i]

:表示i到

len 這個字尾在所有字尾中的排名 sa

[i] :表示排名為

i 的字尾的首字元下標 he

ight

[i]:表示相鄰兩個排名的字尾的最長公共字首的長度 h[

i]:表示i到

len 這個字尾與它前一名字尾的最長公共字首的長度,就是he

ight

[ran

k[i]

]首先基數排序:就是低位到高位一位一位桶排,詳見baidu

怎麼排序?

如果一位一位來,那不就成了暴力了

所以我們要倍增排序

具體來說,對於乙個長度為2k

的字串,我們可以把它看成是兩個長度為2k

−1的字串組成的,那麼就相當於它有兩個關鍵字,我們就從長度為

1 開始,每次對這兩個關鍵字排序不就行了

一張古老的圖

看**

# include 

# define il inline

# define rg register

# define fill(a, b) memset(a, b, sizeof(a))

using

namespace

std;

typedef

long

long ll;

const

int _(1e6 + 5);

int len, sa[_], t[_], a[_], rk[_], y[_];

char s[_];

//t是桶;a和s一樣;rk就是rank;y是輔助rk的陣列,和sa性質相似;sa就是sa

il bool cmp(rg int i, rg int j, rg int k) //確定兩個子串是否相同

il void sort()

}int main(rg int argc, rg char* argv)

有點難理解,多看幾個部落格就可以了有個s

a和ra

nk並沒有什麼卵用,這個時候就有he

ight

這個美妙的東西

怎麼求?

暴力求o(n

2)顯然不行

那麼這個時候要利用

h 的美妙性質:h[

i]≥h

[i−1

]−1證明:設字尾su

f[k]

和suf

[i−1

] 為兩個相鄰排名的字尾,它們的最長公共字首就是h[

i−1]

同時去掉第乙個字元,那麼就是su

f[k+

1]和s

uf[i

] ,那它們兩個的最長公共字首顯然就是h[

i−1]

−1所以su

f[i]

和排在它前面的字尾的最長公共字首至少是h[

i−1]

−1

那麼h就可以很快求出來了,那麼he

ight

也就能很快求出來了

for(rg int i = 1; i <= len; ++i)

for(rg int i = 1; i <= len; ++i) height[i] = h[sa[i]];

剛剛學**比較醜,而且可能有問題

題去這裡找

題去這裡找

題:給定乙個字串,詢問某兩個字尾的最長公共字首。

就是區間he

ight

的最小值,rm

q 問題

重複子串:字串a在字串b中至少出現兩次,則稱a是b的重複子串。

題:給定乙個字串,求最長重複子串,重複的兩個子串可以重疊。

分析:

只需要求 height 陣列裡的最大值即可

題:給定乙個字串,求最長重複子串,重複的兩個子串不能重疊。

分析:

考慮二分答案,每次二分乙個答案

k ,把he

ight

=k 分組

最長公共字首不小於 k 的兩個字尾一定在同一組。對於每組字尾,只須判斷每個字尾的 sa 值的最大值和最小值之差是否不小於k即可

另外:利用 height 值對字尾進行分組的方法很常用

題:給定乙個字串,求至少出現 k 次的最長重複子串,這 k 個子串可以重疊

分析:

也是二分答案+分組,判斷有沒有乙個組的字尾個數不小於 k

題:給定乙個字串,求不相同的子串的個數。

分析:

每個子串一定是某個字尾的字首,也就是求所有字尾不同字首的個數

每來乙個字尾su

f(i)

就會有,le

n−sa

[i]+

1 的新的字首,又由於有he

ight

個重複的,那麼就是le

n−sa

[i]+

1−he

ight

的貢獻還有很多用法見下面的文獻

羅穗騫 –演算法合集之《字尾陣列——處理字串的有力工具》

字尾陣列小結

搞了這麼多字尾陣列,寫個總結 其實羅穗賽的 裡已經都總結得很清楚了。我這裡對一些 的具體實現細節和一些要注意的地方做一些說明。字尾陣列很重要的三個陣列就是 rank,sa和height了 其中rank i 表示i這個字尾的排名,sa i 表示排在第i位的字尾的首字母位置,height i 表示排名第...

字尾陣列小結

我為什麼要叫小結呢這明明就是個題解包啊 直接偷迪哥的就好辣 差異 大概是個板子,求出 height 陣列後直接單調棧即可 相似子串 首先 子串是字尾的字首 其次 每個字尾貢獻的本質不同子串的數量是 n i 1 he i 因為子串過多所以我們考慮運用上文性質來二分查排名 至於相似度 rmq 即可?sa...

字尾陣列學習小結

這兩天學習了字尾陣列,感想是,果然字尾陣列比網路流可愛的多,就像字串比圖論可愛的多。有模板真好qvq。總結了一下字尾陣列的幾個要點 一.理解rank sa height三個陣列。分別代表所構成的字尾陣列str i 在程式裡並不表現出來 排名後的名次 排名後第i位是str中的哪乙個 str sa i ...