回文自动机 初学



    今天学习了一下回文自动机pam,发现比后缀自动机sam简单好多啊。。。clj那个sam的ppt讲的我头昏脑涨的(叫你弱叫你弱>_<))。简单写一下免得自己忘记。

    几个数组:

    1.像各种自动机一样,用ch[x][c]表示状态x后添加字母c之后转移到的状态。

    2.同样,用sum[x]表示状态x所含的回文串的个数(和sam一样,需要在最后进行统计才能得到完整的答案);用l[x]表示状态x的回文串的长度;

    3.另外,用fa[x]表示状态树中x的父亲;或者说,和AC自动机里面的失配函数一样,表示x匹配失败后转移到的状态。

    有没有觉得和sam一模一样呢??!!没错就是一模一样。不过在线添加就简单多了,不像sam还要拆状态这种。。。

    首先两个初始状态0表示长度为偶数的回文串,1表示长度为奇数的回文串。同样用last表示上一次的字符串的状态编号,假设在x处添加字母c。如果s[x-l[last]-1]!=s[x]就一直沿着失配边往上走,直到相等为止,设此时状态为p。但是会不会出现死循环呢?会的。但是没关系,如果令fa[0]=fa[1]=1且l[1]=-1,就会发现最终会变成s[x-l[1]-1]=s[x]==s[x]就停下来了。那为什么不是fa[0]=fa[1]=0呢?因为单个字节长度为1是奇数嘛。

    好了出现s[x-l[p]-1]=s[x]之后怎么办呢?首先看有没有ch[p][c],如果没有就要新建节点now,且l[now]=l[p]+2因为加上了最前面后最后面的两个。另外,新节点的fa[now],则根据fa[p]得到(和AC自动机是不是一样呢?),在fa[p]往上走时出现的第一个s[x-l[q]-1]==s[x]即fa[now]。

    不管有没有新增节点,最后都要将ch[p][c]=now且sum[now]++。添加过程就没了(没了?没了!)

    然后我们发现添加状态的顺序就是树的一个拓扑序,然后就可以和sam一样得到了。

    好了没了!!??!!确实简单!(麻麻再也不用担心我不会背manacher啦(好像manacher更简单←_←)!)

by lych

2016.2.7

你可能感兴趣的:(字符串,回文自动机)