码迷,mamicode.com
首页 > 其他好文 > 详细

回文机

时间:2019-07-25 21:54:05      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:for   extend   int   ems   额外   pac   set   mat   amp   

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

include <bits/stdc++.h>

using namespace std;
typedef long long ll;

struct Node {
int len, ch[26], fail;
ll cnt;
Node(int len = 0) : len(len), fail(0) {
memset(ch, 0, sizeof(ch));
//下面是维护额外信息
cnt = 0;
}
//string str;
void show() {
printf(" len=%d\n",len);
//printf(" str=%s", str.c_str());
printf(" cnt=%lld\n", cnt);
}
};

const int MAXN = 600000;

//PalindromicAutomaton
struct PAM {
Node nd[MAXN + 5];

int len, top, last;     // len为字符串长度mtop为节点个数,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;
    //printf("!%d\n",nd[last].cnt);
    if(len %100000==0)
        printf("len=%d\n", len);
}

void show() {
    for(int i = top; i >= 0; --i) {
        printf("node:  id=%d\n", i);
        nd[i].show();
        printf("fail:  id=%d\n", 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();
    cout<<"!";
    for(int i = 0; s[i] != '\0'; ++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();
    memset(ans, 0, sizeof(ans[0]) * (n + 1));
    for(int i = pam.top; i >= 2; --i) {
        printf("%d\n",i);
        Node *now = &pam.nd[i];
        Node *fail = &pam.nd[now->fail];
        if(now->len == 1) {
            ans[now->len] += now->cnt;
        } else {
            while((fail->len) > (now->len + 1) / 2)
                fail = &pam.nd[fail->fail];
            if(fail->len == (now->len + 1) / 2)
                ans[now->len] += now->cnt;
        }
    }
    for(int i = 1; i <= min(40, n); ++i)
        printf("%lld%c", ans[i], " \n"[i == n]);
    printf("\n");
}
return 0;

}

回文机

标签:for   extend   int   ems   额外   pac   set   mat   amp   

原文地址:https://www.cnblogs.com/Yinku/p/11243179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!