SAM学习小记

7 篇文章 0 订阅
4 篇文章 0 订阅

手玩了一个晚上,终于发现自己的sam爆栈了。。。
@samjia2000 不是玩你233

前言

SAM——suffix aotu-machine
它(Ta?)是有限状态自动机(FSA)的一种(废话)。
它可以实现以O(n)的状态存下一个字符串的所有字串。
因为它把那些本质相同的字串都映射到一个状态上了。

构造

我们记 Rights 表示子串s在原串中出现的结束位置的集合。
很显然 Right 集合要么重合要么无交集。
因为如果有交集那么肯定一个子串是另一个子串的后缀。
于是我们可以设 Parents 表示 Right 集包含了 Rights 且状态最小的那个。
那么我们就构出了一棵parent树。
我们从parent树上往上跳的过程其实就是后缀合并的过程。
那么我们设trans(x,y)表示状态x和字符y之间的转移。
那么每次我们新加入y,新建一个节点np,就可以沿着上一次能够接上y的节点p,如果trans(p,y)=NULL.
那么我们就把它变成np就好了。
当我们第一个找到tran(p,y)=q的时候,这时候分两种情况讨论。
我们设len(x)表示x状态离根节点的最大距离。

1:len(p)+1=len(q)

也就是说状态q一定时候状态p转移过来的。
既然p能够接受状态np,那么q也一定能接受。
于是就把parent(np)=q就好了

2:len(p+1)>len(q)

这时候q就不一定是由状态p转移过来的,但是它肯定包含一些能够接受状态np的状态。
那么我们把这些状态分离出来,设为nq,那么很显然len(nq)=len(p)+1
然后,praent(q)=parent(np)=nq。
因为nq是由q分离出来的,所以显然也可以接受q。
然后,我们就把所有指向状态q并且能够接受状态np的状态都指向nq就好了。
其他状态显然无用。

应用

因为博主是蒟蒻,所以知道的并不多~
比如,求一个串有多少个不同字串。
因为SAM它自动忽略重复字串,所以可以把它看做一个DAG。
也就是求这张图有多少条路径。
直接DP就好了。
如果求字典序第k大/小呢?
那么我们都处理处每一位有多少条路径了,从小到大搜一搜就好了。
余下的。。。有时间在填坑吧~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值