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

hdu6599 I Love Palindrome String

时间:2019-09-23 22:32:59      阅读:100      评论:0      收藏:0      [点我收藏+]

标签:ini   cst   节点   位置   else   这一   size   for   print   

由样例可知,题目中求的回文串数量,其实是本质不同的回文串数量,这个可以直接用回文树来做。

考虑前半段是回文串这个限制,这个东西回文树不好做,可以再套一个马拉车,然后记录一下插入到回文树的节点中最后一个字符的位置,使用马拉车快速判断这一段的前半段是不是回文串

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#define fo(i, l, r) for (int i = l; i <= r; i++)
#define fd(i, l, r) for (int i = r; i >= l; i--)
#define mem(x) memset(x, 0, sizeof(x))
#define ll long long
using namespace std;
const int maxn = 300050;
ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (!(ch >= 0 && ch <= 9))
    {
        if (ch == -)
            f = -1;
        ch = getchar();
    };
    while (ch >= 0 && ch <= 9)
    {
        x = x * 10 + (ch - 0);
        ch = getchar();
    };
    return x * f;
}

char Ma[maxn * 2];
int Mp[maxn * 2];
void Manacher(char s[], int len)
{
    int l = 0;
    Ma[l++] = $;
    Ma[l++] = #;
    for (int i = 0; i < len; i++)
    {
        Ma[l++] = s[i];
        Ma[l++] = #;
    }
    Ma[l] = 0;
    int mx = 0, id = 0;
    for (int i = 0; i < l; i++)
    {
        Mp[i] = mx > i ? min(Mp[2 * id-i], mx-i) : 1;
        while (Ma[i + Mp[i]] == Ma[i-Mp[i]])
            Mp[i]++;
        if (i + Mp[i] > mx)
        {
            mx = i + Mp[i];
            id = i;
        }
    }
}

const int N = 300010, S = 26;
int all, son[N][S], fail[N], cnt[N], len[N], text[N], pos[N], last, tot;
int newnode(int l)
{
    for (int i = 0; i < S; i++)
        son[tot][i] = 0;
    cnt[tot] = 0, len[tot] = l;
    return tot++;
}
void init()
{
    last = tot = all = 0;
    newnode(0), newnode(-1);
    text[0] = -1, fail[0] = 1;
}
int getfail(int x)
{
    while (text[all - len[x] - 1] != text[all])
        x = fail[x];
    return x;
}
void add(int w,int p)
{
    text[++all] = w;
    int x = getfail(last);
    if (!son[x][w])
    {
        int y = newnode(len[x] + 2);
        fail[y] = son[getfail(fail[x])][w];
        son[x][w] = y;
        pos[y] = p;
    }
    cnt[last = son[x][w]]++;
}
void count()
{
    for (int i = tot - 1; ~i; i--)
        cnt[fail[i]] += cnt[i];
}
char s[maxn];
int slen, s2[maxn];
ll ans[maxn];
int flag;
inline bool check(int l,int r){
    int len = r-l+1;
    if(len==1)return true;
    r = (l+r)>>1;
    len = r-l+1;
    if(len&1){
        int t = l + (len>>1);
        t *= 2;
        return Mp[t]-1 >= len;
    }else{
        int t = l + (len >> 1);
        t = t*2-1;
        return Mp[t]-1 >= len;
    }
}
void dfs(int u, int d)
{
    fo(i, 0, 25)
    {
        if (son[u][i])
        {
            s2[d + 1] = i;
            dfs(son[u][i], d + 1);
        }
    }
    if (d)
    {
        int lenu = d + d - flag;
        int rp = pos[u];
        int lp = pos[u]-lenu+1;
        if(check(lp,rp))ans[d + d - flag] += cnt[u];
    }
}
int main()
{
    int tt = 0;
    int T;
    while (scanf("%s", s + 1) != EOF)
    {
        init();
        memset(ans, 0, sizeof(ans));
        slen = strlen(s + 1);
        fo(i, 1, slen)
        {
            add(s[i] - a,i);
        }
        count();
        Manacher(s+1,slen);
        flag = 0;
        dfs(0, 0);
        flag = 1;
        dfs(1, 0);
        printf("%lld", ans[1]);
        fo(i, 2, slen)
        {
            printf(" %lld", ans[i]);
        }
        putchar(\n);
    }
    return 0;
}

 

hdu6599 I Love Palindrome String

标签:ini   cst   节点   位置   else   这一   size   for   print   

原文地址:https://www.cnblogs.com/hyfer/p/11575134.html

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