- hash
- kmp和ac自動機
- 后綴數組,后綴自動機,后綴樹
- 擴展kmp
- manacher算法
- 回文自動機
- 可刪改的ac自動機
- 不看復雜度亂搞
hash
hash就是把字符串每一位乘以一個階,用于快速判斷字符串是否相等。需要擔心碰撞,相等情況不多的時候可以進行強檢查。
kmp和ac自動機
這兩個本質上是同一個東西,一個是求單串的fail指針,一個是求多串的fail指針,用勢能分析可以知道是線性復雜度。
后綴數組,后綴自動機和后綴樹
后綴數組主流實現是利用桶排和倍增在O(nlogn)內求出后綴的大小順序。之后線性時間求出相鄰名次的最長公共前綴長度的height數組。在求最長不重疊子串時常用技巧是二分答案線性判斷。有時配合height數組的RMQ口味更佳。
后綴自動機通過線性的在線算法構造一個包含所有狀態的自動機。具體建議看這篇個人覺得講的比CLJ的營員資料好的文章。CLJ的ppt只證明了邊和點是線性的,并沒有證明構造過程中對cloneq的重定位是線性的,可以通過勢能分析證明每重定位一次cloneq,可估計q的fail深度比p的深度少一。以最新節點的fail遞歸深度為勢能可證明構造線性。
觀察后綴自動機的fail指針則是逆序字符串的后綴樹。可以推測后綴樹與后綴自動機能力等價。
擴展kmp
跟kmp的算法似乎沒有什么關系,解決的問題是求S的每一個后綴和T的最長公共前綴。
設第i個字符起始的S的后綴與T的最長公共前綴長度為extend[i]。
設第i個字符起始的T的后綴與T的最長公共前綴長度為next[i]。
假設next[1...k]和extend[1...k]和當前S匹配最遠處已知,可以通過next數組立即得到在k+1處以匹配多遠,若超過當前最遠處,則從最遠處往前推。復雜度線性。
如何求next數組,next數組相當于T本身的extend可以用同樣的方法求。
loyinglin的思路:擴展kmp解決的問題同樣可以用后綴自動機解決,將S和T反轉,rev(T)建立后綴自動機,將rev(S)在里面跑,從后往前求extend數組。需要預先dp出每個點的fail指針經過的終止符的最大長度。
擴展kmp依然存在價值因為loyinglin的思路是需要rev(S)跑rev(T)的SAM的離線算法,若改成動態增刪S的最后字符,loyinglin的思路就失效了。
manacher算法
求字符串最長回文的問題,與擴展kmp類似,保留一個匹配最遠的點,通過當前位置回文長度初始設為最遠匹配中心的鏡像長度。若更長,則往前匹配,更新最長長度。復雜度線性。奇數和偶數需要分別回文,可通過插特殊值使算法只跑一次。
問題也可用后綴數組實現。
回文自動機
與后綴自動機類似,可在線性時間構造。回文自動機解決一系列回文串問題。完美替代manacher算法,也補全了后綴自動機解決回文問題不方便的問題。
可刪改的ac自動機
ac自動機的dp的特點在于一旦建立好fail指針,要插入字符串需要全部重新建立,使得dp也要全部重新來過。
要建立可刪改的ac自動機,可以建立logn個ac自動機,第1個自動機放1個串,第2個自動機放2個串,第3個放4個串。。。第logn個放n個串。假如目前有7個串在自動機,則只在第1,2,3個自動機分別存1,2,4個串進行dp。此時再插入一個串,則將第1,2,3自動機消除,8個串全部放入第4個自動機,重建fail指針和dp。因為每個串最多經歷logn個自動機,所以均攤復雜度都只是標準自動機的logn倍。
不看復雜度亂搞
字符串很多題數據是很難卡的,比如對于可刪改的ac自動機能完成的題,很多時候可以用一個普通的ac自動機,不計復雜度的A掉。當你做不出題時,就別看復雜度了,先搞為勝。
總結
其實AC自動機和后綴自動機就能解決絕大部分題目了。回文自動機在解決回文串時有它的價值。后綴數組和擴展kmp以備不時之需。