HDU 6599 Palindromic_Automaton

数据结构 专栏收录该内容
54 篇文章 0 订阅

回文自动机插入的时候判断合法性

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N=3e5+10;
ll p[N],FH[N],BH[N];
ll getF(int l,int r){return FH[r]-FH[l-1]*p[r-l+1];}
ll getB(int l,int r){return BH[l]-BH[r+1]*p[r-l+1];}
int check(int l,int r){return getF(l,r)==getB(l,r);}
int ans[N];
struct Palindromic_Automaton {
    int ch[N][26], f[N], len[N], s[N], ok[N];
    int cnt[N]; // 结点表示的本质不同的回文串的个数(调用count()后)
    int num[N]; // 结点表示的最长回文串的最右端点为回文串结尾的回文串个数
    int last, sz, n;
    int newnode(int x) {
        memset(ch[sz], 0, sizeof(ch[sz]));
        cnt[sz] = num[sz] = 0, len[sz] = x;
        return sz++;
    }
    void init() {
        sz = 0; newnode(0), newnode(-1); last = n = 0, s[0] = -1, f[0] = 1;
    }
    int get(int u) {for (; s[n - len[u] - 1] != s[n]; u = f[u]); return u;}
    void add(int c) {
        s[++n] = c;
        int u = get(last);
        if (!ch[u][c]) {
            int np = newnode(len[u] + 2);
            f[np] = ch[get(f[u])][c];
            num[np] = num[f[np]] + 1;
            ch[u][c] = np;
            ok[np]=check(n-len[np]+1,(2*n-len[np]+1)/2);
        }
        last = ch[u][c];
        cnt[last]++;
    }
    void count(){
        for (int i = sz - 1; ~i; i--) cnt[f[i]] += cnt[i];
        for(int i=sz-1;i>1;--i)ans[len[i]]+=cnt[i]*ok[i];
    }
}pam;
char s[N];
int main(){
    p[0]=1;for(int i=1;i<=N-10;++i)p[i]=p[i-1]*131;
    while(scanf("%s",s)!=-1){
        memset(ans,0,sizeof ans);
        int n=strlen(s);
        for(int i=0;i<n;++i)FH[i+1]=FH[i]*131+s[i]-'a';
        for(int i=n;i>0;--i)BH[i]=BH[i+1]*131+s[i-1]-'a';
        pam.init();
        for(int i=0;i<n;++i)pam.add(s[i]-'a');
        pam.count();
        for(int i=1;i<=n;++i)cout<<ans[i]<<(i==n?"\n":" ");
    }
}

 

  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值