入门后缀自动机的一点感悟

前一阵子忙着考试,虽然说后缀自动机一直拖了个把月,但是还是一直没搞,昨天终于全部都考完了,今天下午才把后缀自动机稍微弄明白了一下下。刷了一个最水的spoj入门题目。

当然,这个入门题目也不是那么容易就ac的,前后总共wa了我十多发,终于在内牛满面中a了此题,不容易呀。

言归正传,我稍微说一下我对后缀自动机的理解。

首先说一下自动机。自动机其实可以看成是一个有向图(个人看法),每个点都表示一个状态,如果从A状态可以转到B状态,那么就相当于有一条从A到B的边了。

后缀自动机也是一样。假设我们有一个串ABCBD,假如我们已经对这个串建立好了自动机,那么D所在的那个状态(先不管具体是那个点)可以表示的状态可以是:D,BD,CBD,BCBD,ABCBD。也就是说状态就是后缀。

 

说完了对SAM(后缀自动机)的大概印象了,下面说说具体的实现过程吧。

 

一开始,我是这样想的,对于新插入的一个点,我们只需要从原点,和上次插入的最后一个点对这个新点连接一条边不就可以了?额、、、理论上是没有错的额。为什么呢?因为,后缀自动即表示的是子串嘛,从原点连接到新点,说明任意一个位置都可以作为子串的开始,连接最后一个点的原因是因为,前面所有的状态要想到达这个状态,必须经过它前面的这个字符(连续子串嘛)。但是这样做会产生一些严重的问题,首先就是效率低,因为没有把点数和边数减少到最低。第二个问题也是最严重的问题就是可能存在重复的状态,例如ABCABC,如果按照我说的这个方法开搞,那么两个C所在的状态都可以表示ACB这个子串,这样一来,自动机也就失去了其存在的意义了。

正确的做法是这样的。

首先说明几个字符串的含义:1、next[][26]:当前状态链接一个字符后转移到的状态  2、pre[]:当前状态匹配失败是转移到的状态  3、step[]从原点表示丛原点到当前状态的子串的长度,但是由于子串不是唯一的(后面说),所以表示的为最长的长度。

对于一个串T,假设我们已经构建好了T所对应的自动机。现在需要新加入一个字符X,链接在T的后面。

假设p为T字符串处理完成后的最后的一个点,那么从p开始沿着p的pre指针一直往前走,并且操作next[p][]=新点,知道前面没有点,或者存在一个已经有next指针的点。

然后再进行距离判断。判断距离无非就是保证没有重复的状态,提高效率。这里就不详细讲了。吃饭去了。哈哈,其实后缀自动机真的比AC自动机容易写好多。

接下来还有一些SAM的性质,等我知道了后再说手吧。

现在不说了,我去吃饭啦。

posted @ 2014-06-18 17:40  092000  阅读(474)  评论(0)    收藏  举报