后缀自动机总结……

【有用qu的资料】

1.总之学SAM就去看clj学长的ppt就好,浅yilianmengbi

2.以及这个blog……模拟SAM运行的过程十分到位

http://www.cnblogs.com/oyking/archive/2013/08/02/3232872.html

3.这个blog的总结,大概有一群启发

http://blog.sina.com.cn/s/blog_8fcd775901019mi4.html

4.这里大概算是SAM题集锦了?

http://blog.csdn.net/thy_asdf/article/details/51569443

 

 

字符串处理的话,如果不是鬼畜dp,大概大爷们第一眼hash第二眼就是后缀数组后缀树后缀自动机了。弱菜我一看SA那谜一般的颜值就选择了SAM【望天】。

SAM其实应该是一只(为了节约空间而从一只trie树简化成的)DAG,优秀的性质就是原本n^2级别的点的个数被优化到了线性级别……然而这个优化的思想……亦可赛艇

 

首先是一堆鬼畜的名词,right集合,parent树,某节点(状态)的minmax。这些先不管,也先不管如何建SAM以及它的正确性。我们先考虑SAM如何做到在大量减少节点个数的情况下不造成信息的缺失

1)首先,SAM比起trie树,是一只DAG。也就是说,同一个节点,从根到达的方式很可能不止一种。因此同一个节点可以表示多个子串。

2)如果只用SAM记录一个字符串的所有子串,可以按照trie树的遍历方式直接dfs,显然可以得到所有子串。

3)因为是一只DAG,显然对于一个节点i,无论到达i的路径长什么样子,以i为源点的子图(意会一下反正就是从i出发可以到达的点和这个过程中经过的边的集合)必然是不受影响的,于是在预处理的时候,可以O(点的个数)地处理这些点的子图的信息,在查询的时候可以O(1)地获取这个子图的信息。而这个性质和树十分相似,所以会有一些丧心病狂的SAMdp

 

反正SAM的代码十分好背,不如仔细理解一下那些鬼畜名词好了。

━对于SAM的一个状态,代表了多个子串。

1.这个状态的right集合就是此状态代表的子串们在原串中的结束位置的并集。于是right集合有一个很优美的性质→一个状态right集合的大小就是这个点所代表子串在原串中的出现次数。

2.每个状态有一个pre(或者father或者parent反正只是个名字,就算叫fail也是支持的)指针。在进行匹配的时候,这个pre的作用和AC自动机里的fail指针类似。而对于一个状态ipre[i]表示在right集合包含iright集合的状态中,集合中元素个数最少的那个状态。

3.这个状态代表的串的长度是一个区间,min是这个区间的最小值,max是这个区间的最大值。

━赌五毛上面那一堆看不懂,不如先分析一下;

1.对于一个串s,它的一个子串ss可以在s中出现若干次,而ss的若干个结尾位置的并集就是那个 可以表示子串ss的状态iright集合,将这个集合记为R

2.如果我们对ss进行一种操作,每次操作去掉ss的首字母,设若干次操作后得到的字符串为ss’,ss’必然为s的子串,且在进行操作次数较少时,有可能ss’和ssright集合相等。而当right集合发生变化时,一定只会增加一些元素。

3.于是对于right集合相同的字符串,表示它们的状态所能够进行的转移必然也是相同的,因此,他们在SAMDAG中,后继的节点也可以重复使用,这就是SAM节约空间的原理。

4.对于两个子串ab,设aright集合为RAbright集合为RB,状态ia可以表示a,状态ib可以表示b。若RARB的真子集,则b必然是a的后缀,且在parent树中,ib定为ia的祖先。

 

来考虑如何建立一个SAM

1.先考虑在O(n^2)地建立后缀树时,在得到关于一个字符串s的后缀树后,可以极快地构建关于s+’x’的后缀树(只需要在结束每个结束节点标号为’x’的边指向的节点定义为新的结束节点即可。

2.而SAM是一棵压缩成DAG的后缀树。不妨假设它也有这个性质。

3.我们来考虑如何进行这个[修改结束节点]的操作。

i) 对于可以表示整个串s的节点i,它在parent树上的祖先必然都可以表示s的后缀,因此要对这条链上的节点进行修改;

ii) 在发现某个祖先节点已经有了’x’这个儿子时,并不能直接对像在trie树上一样直接对这个节点进行操作,因为这是DAG,这个儿子可能是公用的,如果直接修改的话,可能会影响其他节点的信息。

iii) 此时,可以判断一下若进行修改是否会有信息丢失,若有则新建一个儿子节点,来单独记录这个结束信息,并且因为不能影响它后续的访问,将原有儿子节点的转移信息全部复制到新建的节点中。

若有信息丢失,则应为max集合变小(详见cljppt),因此在判断时只需要对比当前冲突节点及其儿子的max值。

iv) 同样的,parent树上的父子关系也需要进行更新。

4.关于right集合大小的计算,在赋初值的时候只需要给“np”部分的赋值为1right集合大小完全可以从儿子到父亲地dp上去。

只有np会赋值为1的原因,是只有np中会有新出现的一个right集合的元素,也

就是当前npdis值。而这个值并不存在于当前节点子树中的任一节点的right集合中。

 

 

反正……SAM的代码还是很好写的嘛。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值