往事太多,有時候忘了就忘了吧。
如果有非記不可的,就只能用點附加手段啦!
我們定義一棵往事樹是乙個 n 個點 n-1 條邊的有向無環圖,點編號為 1到 n,其中 1 號點被稱為是根結點,除根結點以外,
每個點都恰有一條出邊(即以其作為起點的邊)。
每條邊上有 1 個字元(這裡我們實際上用乙個不大於 300的非負整數代表不同的字元),
對於任意乙個點 u,u 的所有入邊(即以其為終點的邊)上的字元互不相同。
接下來我們定義往事,點 u 對應的往事為 u 到根的路徑(顯然有且只有一條)上的所有邊按照從 u 到根經過的順序排序後邊上的字元依次拼接形成的字串,簡記為 r(u)。
一棵往事樹的聯絡度取決於它包含的所有往事之中最相近的一對的相似度。具體的,我們定義 2 個點 u 和點 v 對應的往事的相似度 f(u,v)如下。
\(f(u,v)=lcp(r(u),r(v))+lcs(r(u),r(v))\)首先,將所有r(u)排序,這樣,lcp就是相鄰的r(u)的lcp的rmq。(原理同字尾陣列)
所以,排序後離得越近,lcp就越長。
顯然,lcs就是lca的深度。
所以,列舉lca,即對樹進行dfs,每次合併所有子樹,並能詢問所有間隔最近的rmq的最大值。
用線段樹合併,維護每個區間的lcp最大值,排名最大的節點,排名最小的節點,pushup時考慮左子節點的最大值和右子節點的最小值。
這步的時間複雜度是nlogn的。
考慮如何排序:
直接qsort,每次cmp二分+hash比較大小是logn的,總時間複雜度是nlog^2n的。
考慮另一種做法:
若我們已知長度為x的串的大小關係(排名),那麼,我們將長度為x的串拼接在一起,就能得到長度為2x的串。
將長度為2x的串的前半部分的排名作為第一關鍵字,後半部分的排名作為第二關鍵字,排序後就能得到長度為2x的串的大小關係,進而得出長度為2x的串的排名。
然後,我們就可以繼續這個過程,從而將所有r(u)排序。
由於排名是0~n的,所以可以採用基數排序,每輪時間複雜度是線性的,共logn輪,所以總時間複雜度是nlogn。
其實就是字尾陣列的方法。
現在考慮求height(好像不能用字尾陣列的那個方法):
方法一:二分+hash。
方法二:倍增,每次考慮x往上長度為2i的串與y往上長度為2i的串是否相等。
可以發現,這些串,在倍增排序時就考慮過了,若排名相等,這兩個串就相等。將每次倍增排序的排名記錄下來就行了。
總時間複雜度:\(o(nlogn)\)。
**沒了。
trie上構建字尾陣列
往事太多,有時候忘了就忘了吧。如果有非記不可的,就只能用點附加手段啦 我們定義一棵往事樹是乙個 n 個點 n 1 條邊的有向無環圖,點編號為 1到 n,其中 1 號點被稱為是根結點,除根結點以外,每個點都恰有一條出邊 即以其作為起點的邊 每條邊上有 1 個字元 這裡我們實際上用乙個不大於 300的非...
Trie上的字尾陣列
亦稱為廣義字尾陣列 lcs longest common suffix lcp longest common preffix sv s v表示trie上節點v到根的路徑形成的字串 由於在trie上,自帶去重功能 顯然l cs s u,sv de plca u,v lcs su,sv depl ca ...
CH601字尾陣列 Trie樹
內含字典樹建立及查詢模板 描述給定n個字串s1,s2.sn,接下來進行m次詢問,每次詢問給定乙個字串t,求s1 sn中有多少個字串是t的字首。輸入字串的總長度不超過10 6,僅包含小寫字母。輸入格式 第一行兩個整數n,m。接下來n行每行乙個字串si。接下來m行每行乙個字串表示詢問。輸出格式 對於每個...