• 回文树模板


    具体理解看博客就可以了

    下面是一些数组的定义,这是必须要记住的

    每个结点i表示从根到结点i路径上字符链代表的回文串
    int fail[];//类似ac自动机的失配指针
    int cnt[];//当前结点表示的回文串在原串中出现次数
    int num[];//结点i可以向前fail的次数,也可以看作结点i作为右端点可代表的回文串后缀
    int len[];//结点i代表的串的长度
    int n;//插入字符长度
    int p;//结点个数,出去两个初始结点,剩下的结点数就是串中本质不同的回文串的个数
    #include <bits/stdc++.h>
    using namespace std;
     
    const int MAX = 512345;
    const int ALP = 26;
     
    struct Palindromic_Tree {
        int son[MAX][ALP]; //转移边
        int fail[MAX]; //fail 指针
        int cnt[MAX]; //当前节点表示的回文串在原串中出现了多少次
        int num[MAX]; //当前节点 fail 可以向前跳多少次
        int len[MAX]; //当前节点表示的回文串的长度
        int S[MAX]; //插入的字符串
        int last; //最后一次访问到的节点,类似 SAM
        int n; //插入的字符串长度
        int p; //自动机的总状态数
     
        int newnode(int l) {
            memset(son[p], 0, sizeof(son[p]));
            cnt[p] = 0;
            num[p] = 0;
            len[p] = l;
            return p++;
        }
     
        void init() {
            p = 0;
            newnode(0);
            newnode(-1);
            last = 0;
            n = 0;
            S[n] = -1;
            fail[0] = 1;
        }
     
        int get_fail(int x) {
            while (S[n - len[x] - 1] != S[n]) x = fail[x];
            return x;
        }
     
        void add(int c) {
            c -= 'a';
            S[++n] = c;
            int cur = get_fail(last); //通过上一次访问的位置去扩展
            if (!son[cur][c]) { //如果没有对应的节点添加一个新节点
                int now = newnode(len[cur] + 2);
                fail[now] = son[get_fail(fail[cur])][c]; //通过当前节点的 fail 去扩展出新的 fail
                son[cur][c] = now;
                num[now] = num[fail[now]] + 1; //记录 fail 跳多少次
            }
            last = son[cur][c];
            cnt[last]++; //表示当前节点访问了一次
        }
        void count() {
            //如果某个节点出现一次,那么他的 fail 也一定会出现一次,并且在插入的时候没有计数
            for (int i = p - 1; i >= 0; i--) cnt[fail[i]] += cnt[i];
        }
    } AUT;
     
    char data[MAX];
    int n;
     
    int main() {
        scanf("%s", data);
        n = strlen(data);
        AUT.init();
        for (int i = 0; i < n; i++) AUT.add(data[i]);
        AUT.count();
        long long ans = 0;
        for (int i = 0; i < AUT.p; i++) {
            ans = max(ans, 1ll * AUT.len[i] * AUT.cnt[i]);
        }
        printf("%lld
    ", ans);
    }
  • 相关阅读:
    树状数组
    1424:【例题3】喷水装置
    Matrix (二分套二分
    素数筛
    快速幂
    CentOS6/7-防火墙管理
    Ubuntu15.04 python升级到python-3.6.x
    查看Linux系统用户登录日志
    [shell]查找网段内可用IP地址
    最小化安装Linux的常用配置整理
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11248545.html
Copyright © 2020-2023  润新知