后缀自动机算法复习回顾
发布日期:2021-06-27 15:38:09 浏览次数:2 分类:技术文章

本文共 2338 字,大约阅读时间需要 7 分钟。

讲解

本篇博文其实只是笔者个人的做法复习笔记罢了,

如果是为学习后缀自动机不小心点进来的看官们,

我推荐先看 ,名副其实。

实现

0.Structure

struct SAM{
int s[MAXC],fa; int len; SAM(){
memset(s,0,sizeof(s));fa=len=0;}}sam[MAXN<<1];

1.建立:插入点

新点 c ( c h a r ) c_{(char)} c(char) 插入末端 → l e n n p = + + c n t len_{np=++cnt} lennp=++cnt 赋为 l e n p = l a s t + 1 len_{p=last}+1 lenp=last+1

→ 往 p p p 的父亲找, p = f a p p=fa_p p=fap,沿途把无 s [ c ] s[c] s[c] 的点连向 n p np np
然后 →
① ① 直到结束无 s [ c ] s[c] s[c] f a n p fa_{np} fanp 赋为 1。

② ② 找到第一个 s [ c ] s[c] s[c] 记为 q q q

                         C a s e    # 1    \;\;\;\;\;\;\;\;\;\;\;\;Case\;\#1\; Case#1 l e n q = = l e n p + 1 len_q==len_p+1 lenq==lenp+1,直接把 f a n p fa_{np} fanp 赋为 q q q

                         C a s e    # 2    \;\;\;\;\;\;\;\;\;\;\;\;Case\;\#2\; Case#2 l e n q > l e n p + 1 len_q > len_p+1 lenq>lenp+1 e n d p o s n p endpos_{np} endposnp(位置集) 不是 e n d p o s q endpos_q endposq 的子集,不能连父亲,于是把 q q q 拆了:

新建点 n q = + + c n t , s a m [ n q ] = s a m [ q ] nq=++cnt,sam[nq]=sam[q] nq=++cnt,sam[nq]=sam[q],把 q q q 先全部复制到 n q nq nq
l e n n q = l e n p + 1 len_{nq}=len_p+1 lennq=lenp+1
→ 把 f a q fa_{q} faq f a n p fa_{np} fanp 赋为 n q nq nq
→ 继续往 p p p 的父亲找, p = f a p p=fa_p p=fap ,把 s [ c ] = = q s[c]==q s[c]==q 的改为连向 n q nq nq

图示:

在这里插入图片描述

模板:

int las = 1,cnt = 1;int f[MAXN<<1]; //extravoid addsam(int c) {
int p = las; int np = (las = ++ cnt); f[np] = 1; //extra sam[np].len = sam[p].len + 1; for(;p && !sam[p].s[c];p = sam[p].fa) sam[p].s[c] = np; if(!p) sam[np].fa = 1; else {
int q = sam[p].s[c]; if(sam[q].len == sam[p].len + 1) sam[np].fa = q; else {
int nq = ++ cnt;sam[nq] = sam[q]; sam[nq].len = sam[p].len + 1; sam[np].fa = sam[q].fa = nq; for(;p && sam[p].s[c] == q;p = sam[p].fa) sam[p].s[c] = nq; } } return ;}

2.处理出现次数

注意到上面注释 //extra 的地方,即是出现次数的初步处理

然后根据 f a fa fa p a r e n t    t r e e parent\;tree parenttree 建出来,从叶子开始加上去

模板:

vector
g[MAXN<<1];void build_Parent_Tree() {
for(int i = 2;i <= cnt;i ++) g[sam[i].fa].push_back(i);}void dfs(int x) {
for(int i = 0;i < (int)g[x].size();i ++) {
dfs(g[x][i]); f[x] += f[g[x][i]]; }}

3.用法

  • SAM 和 Parent Tree 高度统一,SAM 上每个点存的出现次数同时也是 Parent Tree 上每一等价类中所有子串出现次数
  • Parent Tree 中的父边在字符串匹配时可以当 AC 自动机中的 fail 边用
  • 由于 SAM 是个 DAG ,可以进行 DAG 的各种操作,拓扑、DP、…
  • ( T o    b e    c o n t i n u e d ) (To\;be\;continued) (Tobecontinued)

转载地址:https://blog.csdn.net/weixin_43960414/article/details/111990471 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【ICPC 2020上海区域赛】Traveling in the Grid World(平面几何)
下一篇:CF1261F Xor-Set (拆区间、扫描线)

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月14日 22时20分18秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

【Linux】设置防火墙让外界访问服务器 2019-04-28
【webservice】通过webservice判断手机卡号类型 2019-04-28
【leetcode之旅】 数组 - 414.第三大的数 2019-04-28
【leetcode之旅】 数组 - 448.找出所有数组消失的数 2019-04-28
【leetcode之旅】 数组 - 485.最大连续1的个数 2019-04-28
【leetcode之旅】 数组 - 561.数组拆分I 2019-04-28
Android面试必问!我的移动开发春季历程,大厂内部资料 2019-04-28
Android面试送分题:来看看移动端小程序技术的前世今生!附赠课程+题库 2019-04-28
Android面试题整理,46道面试题带你了解中高级Android面试,顺利通过阿里Android岗面试 2019-04-28
上海大厂Android面试经历:Android多线程实现方式及并发与同步,年薪超过80万! 2019-04-28
从入门到精通!已成功拿下字节、腾讯、脉脉offer,看看这篇文章吧! 2019-04-28
金九银十Android热点知识!如何快速的开发一个完整的直播app,内含福利 2019-04-28
金九银十Android热点知识!字节跳动移动架构师学习笔记,面试真题解析 2019-04-28
阿里P7亲自教你!34岁安卓开发大叔感慨,Android面试题及解析 2019-04-28
阿里P7大佬手把手教你!系统盘点Android开发者必须掌握的知识点,系列篇 2019-04-28
阿里P7大牛手把手教你!十多家大厂Android面试真题锦集干货整理,聪明人已经收藏了! 2019-04-28
阿里P7大牛整理!腾讯+字节+阿里面经真题汇总,书籍+视频+学习笔记+技能提升资源库 2019-04-28
android面试准备中高级简书!致Android高级工程师的一封信,内含福利 2019-04-29
Android面试回忆录:2个月面试腾讯、B站、网易等11家公司的面经总结!3面直接拿到offer 2019-04-29
Android面试回忆录:在字节跳动我是如何当面试官的,面试心得体会 2019-04-29