后缀自动机…真的好难啊…….
想学的可以看陈立杰课件……以及众多题解
这里贴个模板吧,还是很短的!而且比后缀数组快!
inline void ins(int ch){
int p=last,np=++cnt;mx[np]=mx[p]+1;last=np;size[np]=1;
while(p && !son[p][ch]) son[p][ch]=np,p=fa[p];
if(!p) fa[np]=root;
else{
int q=son[p][ch];
if(mx[q]==mx[p]+1) fa[np]=q;
else{
int nq=++cnt;mx[nq]=mx[p]+1;
memcpy(son[nq],son[q],sizeof(son[nq]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
while(son[p][ch]==q) son[p][ch]=nq,p=fa[p];
}
}
}
后缀自动机用处也挺多的…除了空间贼大…..
比如可以找最长公共子串
比如找最小表示法
比如…..
题目
最长公共子串问题
一般来说,解决最长公共子串的问题,我们会根据一个串建立SAM,然后用剩下的串在上面匹配,然后再考虑别的问题
例题
- spoj1811 LCS 两个串最长公共子串 模板吧
- spoj1812 LCS2 多个串的最长公共子串 需要多记几个值来看看
- 题解戳这里哟~
最小表示法问题
这类题并不多啊…求循环最小表示法的话,就把字符串循环两遍建SAM就好
例题:bzoj2882/洛谷1368 工艺 就最小表示法… 题解戳这里哟~
求第k小字符串问题
其实和找最小差不多,把字符串建成一个SAM,从下向上(找拓扑序,具体可以看下面的后缀自动机+dp问题)统计个数,然后深搜找最第 k 小
例题:bzoj3998/洛谷3975 [TJOI2015]弦论 就单纯求第k小,没什么好说的题解戳这里哟~
后缀自动机+dp问题
这类题真的超多…感觉都跟dp脱不了关系【捂脸】
这类题大部分要求一下拓扑序,然后dp回去。因为要从叶节点更新 fa 的结果,或从fa更新叶节点结果。求拓扑序,就基数排序就好
但是还是好难…算了上题吧
题目
- spoj8222 Substrings 最基本的吧,从下往上累计下个数 题解戳这里哟~
- 洛谷P3804【模板】后缀自动机 记录个数,从下向上推吧 题解戳这里哟~
- bzoj4516/洛谷P4070 [Sdoi2016]生成魔咒 模板题….题解戳这里哟
- bzoj4566/洛谷3181 [Haoi2016]找相同字符
感觉这个很难想啊…可能我的dp还是太差了。
要注意一个地方,假如能够匹配到某一个点,那么它的所有父节点都是能到的,都要加起来
题解戳这里哟~
后缀自动机+各种维护….
这类..也只能见一道做一道了….
在这里,后缀自动机差不多就只是一个模板了…重点还是看怎么维护
题目
- bzoj2555 SubString
有添加操作,所以连边会发生变化,因此考虑LCT维护…贼难写 题解戳这里哟~ bzoj3238/洛谷4284 [Ahoi2013]差异
后缀自动机+lca+dp,枚举每个点…感觉还是很难啊…感觉很难想…不过推荐后缀数组的做法….感觉稍微好想一点 题解戳这里哟~bzoj3676/洛谷3649 [Apio2014]回文串
回文串嘛,显然和回文有关。manacher找到所有回文去找最大值。然而这样是会tle的…所有以一种做法的倍增…..倍增出各个祖先,然后就不tle了。还有一种做法..是张天扬国家集训队候选论文提到的…真的快…而且短….不过特别难想…还是看代码吧 题解戳这里哟~