字尾陣列題目選講

2022-09-20 08:21:11 字數 2488 閱讀 9626

複習題:luogu題單

\(1.\)

noi2015 品酒大會

題意:\(\forall i∈[0,n)\)求有多少對字尾滿足\(lcp \ge i\)​,以及滿足條件的兩個字尾的權值乘積的最大值。

我們統計出對於\(1...n\)中的每個\(i\)統計一下有多少個\(lcp=i\)再做個字尾和。

因為\(lcp(i,j)=min_^st_\times ed_i\)​​,複雜度\(o(n^2)\)​​,這樣就可以拿到\(95pts\)​了​​​​​​,最後5pts打表就行了。

考慮如何更快的求出\(st\)​和\(ed\)​,我們列舉 \(aa\)​ 型字串中\(a\)​的長度\(l\)。每隔\(l\)格放乙個關鍵點,即在\(l,2l,3l...\)位置放關鍵點。顯然,乙個長度為\(2l\)的 \(aa\) 型字串應當經過恰好兩個關鍵點。

設\(lcp(i,j)\)​​為以\(i,j\)​字尾開頭的最長公共字首,\(lcs(i,j)\)​為以\(i,j\)​字尾結束的最長公共字尾,這個可以建正反串字尾陣列求出。考慮兩個相鄰的關鍵點\(i,j\)​,其中\(i+l=j\)​ ,那麼顯然當\(lcp(i,j)+lcs(i,j) \ge l\)​時產生了貢獻,貢獻為\(lcp(i,j)+lcs(i,j)-l+1\)​​

如圖紅色是\(i,j\)​,藍色和綠色分別是\(lcp\)​和\(lcs\)​,其中粉色是\(aa\)​串,而這個\(aa\)​串可以一直向後滑動到棕色部分,滑動中經過的串的個數就是\(lcp(i,j)+lcs(i,j)-l+1\)​​,所以我們把紅色加粗部分的所有\(st_i\)​加\(1\)​,把綠色加粗部分的所有\(ed_i\)​加\(1\)​,這個用差分實現即可。

\(3\)​​.noi2018 你的名字

題意: 給你乙個字串\(s\), 多次詢問給定乙個\(t\), 求\(t\)中不在\(s[l...r]\)​**現的本質不同的子串個數。

老套路,把詢問離線,把所有串用乙個特殊字元連在一起做字尾陣列。

我們按順序列舉\(t\)​​的每個字尾\(i\)​​,我們求出最大的長度\(l\)​​使得\(\large t[i,i+l-1]\)​​是\(s[l...r]\)​​的子串,那麼長度小於\(l\)​​的顯然都不滿足條件,可以直接計算。這個\(l\)​​是可以二分的,但是我們發現所有的\(i+l-1\)​​這個位置隨著\(i\)​​的增大是單調上公升的,所以雙指標即可。

所以現在只要判斷乙個\(l\)​是否可行。事實上就是查詢\(s[l...r-l+1]\)中是否存在乙個\(k\)使得\(lcp(k,i) \ge l\)​,我們先求出滿足這個條件的\(k\)在字尾陣列上的區間\([le,ri]\),然後判斷\([le,ri]\)中是否存在乙個字尾\(k \in [l,r-l+1]\)​,使用主席樹查詢即可。

用本質不同子串個數減去上述得到的答案即可。

時間複雜度\(o(nlog_2n)\),注意常數。

\(4.\)​[heoi2016/tjoi2016 字串

考慮二分答案,二分乙個\(l\)只需要判斷是否存在乙個\(k \in [b-l+1,b]\)使得\(lcp(k,c)=l\),根據上題的做法,先二分求出在字尾陣列的對應的區間\([le,ri]\)​,然後主席樹查詢即可。

時間複雜度\(o(nlog_2^2n)\)

\(5.\)​cf504e

先樹剖再按\(dfn\)序建立正反字尾陣列,跳重鏈的時候記錄下重鏈的左右端點,然後拼起來。

每次我們用\(st\)表求出\(lcp(i,j)\)​然後根據長度判斷是否還能向擴充套件。

因為兩個點之間重鏈個數最多只有\(2log_2n\)個,所以我們最多比較\(4log_2n\)次。

這個做法常數很小,最慢的點只要2s,目前我的賬號周

小涵是\(luogu\)​​​的最優解。

\(6\).cf666e

老套路,把所有串用乙個特殊字元連在一起做字尾陣列。

容易發現答案就是對於所有滿足\(lcp(pl,k) \ge pr-pl+1\)​中\(col_k \in [l,r]\)​的眾數。

我們考慮將詢問按 \(pr-pl+1\)​ 從大到小排序,再把\(heiht_i\)​ 也從大到小排序,用兩個指標,乙個指向當前詢問,乙個指向當前的\(heiht_i\)​,我們將所有\(height_i \ge pr-pl+1\)​的進行合併操作。也就是把\(i\)​和\(i-1\)​​​​所在的集合合併,用資料結構維護眾數即可,很顯然用並查集+線段樹合併可以很好的維護這個資訊。這題的做法和noip2013 貨車運輸的思想是一樣的,所以事實上也可以用\(kruskal\)​​重構樹維護眾數。

\(7.\)

cf1037h

我們列舉答案與\(t\)的\(lcp\)長度\(l\),找出在字尾陣列上對應的區間\([l,r]\),因為新增乙個字元只會使區間縮小,所以我們用兩次二分可以確定新一輪\([l,r]\)。

我們再枚第\(l+1\)​個應該填什麼字元,這個字元應滿足字典序是大於原字串的對應位置的字元,按照上述同樣的方法求出\([l,r]\)​,然後判斷\([l,r]\)​中是否\(\exist~sa_k\in[le,ri-l]\)​,這個用主席樹維護即可。

CodeChef題目選講

關鍵點 不超過7條 根據咕咕原理,所以答案最少是n 7 n小於49就暴力 隨機化找兩個點判斷直線上的點個數,隨機500次,概率就很高了 法二 點數大於50,答案至少是8 答案一定是7條路之一 隨機找7個點,按照級角序排序,點數大於7的直線就刪去上面的點 之後random不考慮,但是實際上不能真刪除,...

貪心題目選講

假定海岸線是一條無限延伸的直線,陸地在海岸線的一邊,大海在另一側。海中有許多島嶼,每乙個小島我們可以認為是乙個點。現在要在海岸線上安裝雷達,雷達的覆蓋範圍是d,也就是說大海中乙個小島能被安裝的雷達覆蓋,那麼它們之間的距離最大為d。我們使用平面直角座標系,定義海岸線是x軸,大海在x軸上方,陸地在下方。...

樹狀陣列選講

樹狀陣列 binary indexed tree bit fenwick tree 是乙個查詢和修改複雜度都為log n 的資料結構。主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改乙個元素的值 經過簡單修改可以在log n 的複雜度下進行範圍修改,但是這時只能查詢其中乙個元素的值。樹狀陣列...