学习后缀自动机想法

来源:互联网 发布:中国石油库存数据 编辑:程序博客网 时间:2024/06/16 13:50
小序:学习后缀自动机是要有耐心的,clj的论文自己看真心酸爽!(还是自己太弱,ls,oyzx好劲啊,狂膜不止)

   刚刚在写博客之前又看了篇论文,终于看懂了,好开心

正文:

  一.后缀自动机是什么?

   答:后缀树+自动机

  二.能处理什么问题?

   答:字符串之类的啊,还要问

  三.有什么优点?

   答:代码短,时间复杂度低

  四.怎么写?

   1.首先你得知道什么是自动机和什么是后缀树?

    这个是基础问题,你可以去查查资料,本文不再阐述。

   2.后缀树建树点是N2的,怎么破?

    clj的ppt写的很详细,但是不是很容易懂,于是我这个蒟蒻就讲讲吧。

    (1).我们要破点又要能表示所有的状态势必就要合并点。

       可是什么样的点是可以合并?

       这可谓是后缀自动机学习需要了解的关键之一,下面我就讲一下我的想法:

       我们首先要定义一个right数组,表示一个子串s在母串ss中的右端点位置集合,例如aab在aabaabab中的right[s]={3,6};

       这个有什么用呢?

       我们来想一个这样的问题如果两个串s1,s2的right集合有交集那会是什么情况?

       先给出结论等下在证明:设sum[right[s]]代表right[s]集合的元素个数,如果两个串s1,s2的right集合有交集,并且sum[s1]>=sum[s2]则s1是s2的子串;

       证明:设right[s1]∩right[s2]={v1,v2,v3.....,vk},就那v1来看吧,那么s1和s2势必是v1前面的某两个点到v1所形成的字符串,那么为什么sum[s1]>=sum[s2]则是s1是s2的子串?一个显然的结论:如果一个子串的sum更大,那么它的长度越短。

       证明了这些东西,那么right集合相等的就可以合并了啊,是不是很神,然后我们就可以利用right集合建一颗树了(可以表示出一个串的从属情况)

       如下图:

               

       这样就可以了吗,能表示所有的子串状态吗?显然是不行的,不然要自动机干嘛(可以自己yy一下)。

    (2).状态数的线性证明.

       clj的ppt非常详细,自己看看吧,我怕我自己的证明不严谨将读者带入歧路。

    (3).构造过程:

       设:已匹配串s,待匹配字符x,已建节点p。

       1.新建节点np,然后从p开始向fa[p]跳,如果有连出为x的边并且val[p]+1=val[son[p][x]]则向np连一条为x的边。否则执行步骤2.

       2.

        

      3.到这里你可能就要大喊一句为什么?为什么要新建节点?

       

            

      论文上写很好,你们如果不理解可以留言问我咯【本蒟蒻QQ:1481632287】

   五.总结:这个东西学起来有点难懂,但是学完了会发现还是很简单的,虽说可能它的用处比后缀数组要小但是它的代码短,又高效这才是更适合oi比赛的东东。

    刚刚发现一个好强的博客:http://blog.csdn.net/wangzhen_yu/article/details/45481269;

    

       

    

   

   

 

0 0