zoukankan      html  css  js  c++  java
  • 模板

    构造一种fail向同一个节点的回文机:
    abadabacaba
    这样caba和daba都会指向ba。

    带展示功能的回文自动机:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    struct Node {
        int len, ch[26], fail;
        int cnt;
        string str;
        Node(int len = 0) : len(len), fail(0) {
            memset(ch, 0, sizeof(ch));
            //下面是维护额外信息
            cnt = 0;
            str="";
        }
        void show() {
            printf("  str="%s"
    ", str.c_str());
            printf("  len=%d cnt=%d
    ",len,cnt);
        }
    };
    
    const int MAXN = 600000;
    
    //PalindromicAutomaton
    struct PAM {
        Node nd[MAXN + 5];
    
        int len, top, last;     // len为字符串长度,top为节点个数,last为最后插入字符所对应的节点
        char s[MAXN + 5];
        string ls;  //用来展示的辅助字符串
    
        int getfail(int x) {        //沿着fail指针找到第一个回文后缀
            while(s[len - nd[x].len - 1] != s[len])
                x = nd[x].fail;
            return x;
        }
    
        void init() {
            len = 0, top = 0, last = 0;
            nd[top] = Node(0);
            nd[top].fail = 1;
            nd[++top] = Node(-1);
            nd[top].fail = 0;
            s[0] = '$';
        }
    
        void extend(char c) {
            s[++len] = c;
            int now = getfail(last);     //找到插入的位置
            ls = nd[now].str + c;   //用来展示的辅助字符串
            if(!nd[now].ch[c - 'a']) {     //若没有这个节点,则新建并求出它的fail指针
                nd[++top] = Node(nd[now].len + 2);
                nd[top].fail = nd[getfail(nd[now].fail)].ch[c - 'a'];
                nd[now].ch[c - 'a'] = top;
            }
            last = nd[now].ch[c - 'a'];
            nd[last].str = ls;  //用来展示的辅助字符串
            //下面是维护额外信息
            ++nd[last].cnt;
        }
    
        void show() {
            for(int i = top; i >= 0; --i) {
                printf("node:  id=%d
    ", i);
                nd[i].show();
                printf("fail:  id=%d
    ", nd[i].fail);
                nd[nd[i].fail].show();
                puts("");
            }
        }
    } pam;
    
    char s[MAXN + 5];
    ll ans[MAXN + 5];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        while(~scanf("%s", s)) {
            int n = strlen(s);
            pam.init();
            for(int i = 0; s[i] != ''; ++i)
                pam.extend(s[i]);
            //pam.show();
            for(int i = pam.top; i >= 2; --i) {
                Node *now = &pam.nd[i];
                Node *fail = &pam.nd[now->fail];
                fail->cnt += now->cnt;
            }
            pam.show();
        }
        return 0;
    }
    
  • 相关阅读:
    bzoj1529: [POI2005]ska Piggy banks
    BZOJ 3065 带插入区间K小值
    【BZOJ做题记录】07.07~?
    【BZOJ2882】【字符串的最小表示】工艺
    【不能继续浪啦】BZ做题记录[7.01~7.06]
    第一次到zhzx到今天已经一周年了
    BestCoder Round #45
    BestCoder Round #41 记。
    BZOJ做题记录[0512~?]
    [BZOJ2809&1455&1367]解题报告|可并堆
  • 原文地址:https://www.cnblogs.com/Yinku/p/11243179.html
Copyright © 2011-2022 走看看