用途:(a)可以在某一字符串中搜索另一字符串的所有出现位置
(b)计算不同子串的个数
线性时间内解决字符串问题
后缀自动机最重要的性质是:它包含了一个字符串所有的字串信息。
后缀自动机是一张有向无环图,边表示状态
一个串的子串有多少之类的问题,或是询问子串/后缀的问题,就用子边转移(自动机性质)。
而计算一个串重复出现次数(right集合的问题),回退到最长匹配状态(LCS问题),就用父边转移(后缀树性质)。
endpos(结束位置)
定义a. 两个非空子串u和v(length(u)<=length(v))是终点等价的,当且仅当u在字符串s中仅作为w的后缀出现。
后缀自动机的应用:
存在性查询
问题:给定文本T,询问格式如下:给定字符串P,问P是否是T的子串。
算法:我们对文本T用O(length(T))建立后缀自动机。
解释:从s状态开始走,沿着串p的字符开始走,如果能够走通则是子串,否则不是
不同子串个数
问题:给定字符串S,问它有多少不同的子串。
算法:构建S后缀自动机,O(n)
解释:S的任意子串都对应SAM中的一条路径,所以路径条数就是子串个数
不同子串的总长
问题:给定字符串S,求其所有不同子串的总长度。
算法:上题类似,加个长度
字典序第k小子串
问题:给定字符串S,一系列询问——给出整数K_i,计算S的所有子串排序后的第K_i个。
复杂度要求:单次询问O(length(ans)*Alphabet),其中ans是该询问的答案,Alphabet是字母表大小。
算法:这一问题的基础思路和上两题类似。字典序第k小子串——自动机中字典序第k小的路径。因此,考虑从每个状态出发的不同路径数,我们将得以轻松地确定第k小路径,从初始状态开始逐位确定答案。
最小循环移位
问题.给定字符串S,找到和它循环同构的字典序最小字符串。
出现次数查询
问题.给定文本T,询问格式如下:给定字符串P,希望找出P作为子串在文本T中出现了多少次(出现区间可以相交)。
首次出现位置查询
问题.给定文本T,询问格式如下:给定字符串P,求P在文本中第一次出现的位置。
所有出现位置查询
问题.给定文本T,询问格式如下:给定字符串P,要求给出P在T中的所有出现位置(出现区间可以相交)。
查询不在文本中出现的最短字符串
问题.给定字符串S和字母表。要求找出一个长度最短的字符串,使得它不是S的子串。
求两个字符串的最长公共子串 √
问题.给定两个字符串S和T。要求找出它们的最长公共子串,即一个字符串X,它同时是S和T的子串。
多个字符串的最长公共子串
问题.给出K个字符串S_1~S_K。要求找出它们的最长公共子串,即一个字符串X,它是所有S_i的子串。