break continue
阿新 • • 發佈:2021-07-26
字尾自動機
水題清單
例題選記
一 P3804 【模板】字尾自動機 (SAM)
題意:
請你求出 S 的所有出現次數不為 1 的子串的出現次數乘上該子串長度的最大值。
做法:
把每次插入字元新建的節點時記為一,之後在parent樹上將兒子的節點值累加到父親上,該處的節點值即為此節點上所有字串的出現次數,即可計算求出答案。
原理:
parent樹上節點的祖先即為該節點字尾,但假如一個新字元時,即為該字首的所有後綴的出現次數加 1,即讓該節點上parent樹上的所有祖先出現次數加 1.
二 P2408 不同子串個數
題意:
求本質不同子串個數。
做法:
列舉每個節點,該節點的 len 減去其父親的 len 即為該節點代表的字串的個數,累加求和即可。
三 SP7258 SUBLEX - Lexicographical Substring Search
題意:
求本質不同排名第k小的子串。
做法:
在建立出的字尾自動機的tire樹上操作即可。
四 SP1811 LCS - Longest Common Substring
題意:
求2 個字串的最長公共子串。
做法:
類似於KMP,在每次匹配失敗時向上跳父親,即為找其後綴,每一次跳完後比較答案。
五 P4248 [AHOI2013]差異
題意:
給定一個字串,
求:
1⩽i<j⩽n∑len(Ti)+len(Tj)−2×lcp(Ti,Tj)
lcp(a,b)表示字串 a 和字串 b 的最長公共字首。
做法:
前兩個一起算,lcp單獨算。
將字串翻轉,即變為求每兩個字首的最長公共字尾。
任意兩個字首的最長字尾就在其 parent 樹的 lca 上,因此在 parent 樹上列舉此節點為多少節點的 lca 即可。記pt陣列表示此節點是否表示字首,siz為此子樹上有多少個字首。
六 [SDOI2016]生成魔咒
題意:
每插入一個字元時,當前本質不同的子串個數。
做法:
每插入一個字元,將其他節點向其連邊時,將ans加上此節點代表子串數。
在字元型別過多時,在結構體裡使用 map 存邊。