zoukankan      html  css  js  c++  java
  • 学习后缀自动机想法

    小序:学习后缀自动机是要有耐心的,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;

        

           

        

       

       

  • 相关阅读:
    PHP连接FTP服务的简单实现
    Map遍历
    线程的互斥与同步
    Java中Collections.sort()排序详解
    Echarts的赋值,设置数据
    JSON和GSON的使用
    发送邮箱验证
    java中获取服务器的IP和端口
    一个题目涉及到的50个Sql语句
    JAVA面试题二
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5547694.html
Copyright © 2011-2022 走看看