zoukankan      html  css  js  c++  java
  • 洛谷P5496 回文自动机【PAM】模板

    回文自动机模板

    1.一个串的本质不同的回文串数量是(O(n))级别的

    2.回文自动机的状态数不超过串长,且状态数等于本质不同的回文串数量,除了奇偶两个根节点

    3.如何统计所有回文串的数量,类似后缀自动机,不需要重新拓扑排序,因为是按节点顺序插入的,所以逆序上传即可

    建树的时候(0)节点为偶数长度回文的根
    (1)节点为奇数长度回文的根

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 5e5+7;
    class PAM{
    private:
        int tot,sz[MAXN],len[MAXN],ch[MAXN][26],fail[MAXN],n,last;
        char s[MAXN];
    public:
        void init(){
            scanf("%s",s+1);
            n = strlen(s+1);
            //0和1分别代表偶数长度回文串的根和奇数长度回文串的根
            len[0] = 0; len[1] = -1;
            fail[0] = 1; fail[1] = 0;
            tot = 1; last = 0;
        }
        int getfail(int x, int pos){
            while(s[pos]!=s[pos-len[x]-1]) x = fail[x];
            return x;
        }
        void insert(int x, int pos){
            int u = getfail(x,pos);
            int c = s[pos] - 'a';
            if(!ch[u][c]){
                len[++tot] = len[u] + 2;
                fail[tot] = ch[getfail(fail[u],pos)][c];
                sz[tot] = sz[fail[tot]] + 1;
                ch[u][c] = tot;
            }
            last = ch[u][c];
        }
        void build(){
            int k = 0;
            for(int i = 1; i <= n; i++){
                s[i] = (s[i]-97+k)%26+97;
                insert(last,i);
                printf("%d ",k = sz[last]);
            }
        }
    }pam;
    int main(){
        pam.init();
        pam.build();
        return 0;
    }
    
    
  • 相关阅读:
    (4)使用 JDK8 日期時間 API
    (3)使用 Joda-Time
    (2)時間的 ABC
    (1)Date 與 Calendar 怎麼了?
    Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?
    AsyncTask 源码阅读笔记
    LinkedHashMap 阅读笔记
    HashMap 阅读笔记
    DiskLruCache 阅读笔记
    Android面试复习
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12826514.html
Copyright © 2011-2022 走看看