zoukankan      html  css  js  c++  java
  • 回文自动机(PAM) 学习笔记

    原文链接www.cnblogs.com/zhouzhendong/p/PAM.html

    前置知识

    无。

    (强行说和KMP有关也是可以的……)

    关于回文串的一些性质

    1. 一个长度为 n 的字符串最多有 n 个本质不同的回文子串。

    2. 对于一个字符串 S,如果在其之后新插入一个字符,那么最多产生一种新的回文子串。

     证明:

      假设加入这个字符之后得到的最长回文后缀为 T,那么对于长度小于 T 的任何回文后缀,它们必然在更前面的位置出现过。如图所示:

        

      所以只有 T 可能是新的回文子串。

    构造PAM

      记 len[x] 表示节点 x 代表的回文串长度,设 Fail[x] 表示“代表 节点 x 所代表的回文串的最长回文后缀 的节点”。(注意这里的最长回文后缀是指长度小于原串的最长回文后缀,和后面提到的意义有差别)

      设 Next[x][c] 表示节点 x 所代表的字符串在前后都加上一个字符 c 之后所到达的状态。则必然有 len[x] + 2 = len[Next[x][c]] 。

      首先,我们建两个节点 A 和 B 。设 len[A] = -1, len[B] = 0 。

      于是长度为 1 的回文串就可以有 A 走转移边到达。

      接下来考虑如何构建 PAM 。

      考虑增量法,在串 s 后面加入一个字符 c 后, PAM 变成了怎样?

      假设当前插入的字符是 s[i],字符串 s 的第 k 个字符为 s[k] 。

      设 x 表示 s 的最长回文后缀,那么如果 s[i - len[x] - 1] = s[i] ,那么最长回文后缀就是 Next[x][s[i]];否则不断使 x = Fail[x] ,直到满足条件就找到了 s 的最长回文后缀。

      找到之后,如果 Next[x][s[i]] 这个节点已经存在,那么什么也不用干;否则,我们新建一个节点代表 Next[x][s[i]] , len[Next[x][s[i]]] = len[x] + 2 ,那么如何求 Fail[Next[x][s[i]]] ?

      考虑找到使 x = Fail[x] ,末尾加入字符 s[i] 之后,再找一次最长回文后缀即可。

    模板

    namespace PAM{
        int len[N],Fail[N],Next[N][26];
        int cnt;
        void init(){
            cnt=2;
            len[1]=-1,Fail[1]=1;
            len[2]=0,Fail[2]=1;
            clr(Next);
        }
        void build(char *s,int n){
            init();
            s[0]='*';
            int x=1;
            for (int i=1;i<=n;i++){
                while (s[i-len[x]-1]!=s[i])
                    x=Fail[x];
                int c=s[i]-'a';
                if (Next[x][c])
                    x=Next[x][c];
                else {
                    int y=Next[x][c]=++cnt;
                    len[y]=len[x]+2;
                    if (len[y]==1)
                        Fail[y]=2;
                    else {
                        x=Fail[x];
                        while (s[i-len[x]-1]!=s[i])
                            x=Fail[x];
                        Fail[y]=Next[x][c];
                    }
                    x=y;
                }
            }
        }
    }
    

    模板题

    UOJ#103. 【APIO2014】Palindromes

    传送门:http://uoj.ac/problem/103

  • 相关阅读:
    1.1 java变量及数据类型
    3. 软件测试的类型
    2.3 软件测试模型之 敏捷测试
    2.2 软件测试的手段
    2.1 软件测试的阶段
    1.1 软件测试基础概念
    浅谈内联元素inline
    微信内置浏览器清除缓存的方法
    我的package.json清单
    我的gulp.js清单
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/PAM.html
Copyright © 2011-2022 走看看