后缀自动机应用及例题

后缀自动机…真的好难啊…….
想学的可以看陈立杰课件……以及众多题解

这里贴个模板吧,还是很短的!而且比后缀数组快!

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]; 
        }
    }
}

后缀自动机用处也挺多的…除了空间贼大…..
比如可以找最长公共子串
比如找最小表示法
比如…..


题目

  • 题目
    • 最长公共子串问题
    • 最小表示法问题
    • 求第k小字符串问题
    • 后缀自动机+dp问题
    • 后缀自动机+各种维护….

最长公共子串问题

一般来说,解决最长公共子串的问题,我们会根据一个串建立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了。还有一种做法..是张天扬国家集训队候选论文提到的…真的快…而且短….不过特别难想…还是看代码吧 题解戳这里哟~

你可能感兴趣的:(后缀自动机)