[hdu6599]I Love Palindrome String

Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)

分数:回文自动机初见,2500
Problem Description

You are given a string S = s 1 s 2 . . s ∣ S ∣ S=s_1s_2..s_{|S|} S=s1s2..sS containing only lowercase English letters. For each integer i ∈ [ 1 , ∣ S ∣ ] i∈[1,|S|] i[1,S], please output how many substrings s l s l + 1 . . . s r s_ls_{l+1}...s_r slsl+1...sr satisfy the following conditions:
r − l + 1 r−l+1 rl+1 equals to i i i.
∙ The substring s l s l + 1 . . . s r s_ls_{l+1}...s_r slsl+1...sr is a palindrome string.
s l s l + 1 . . . s ⌊ ( l + r ) / 2 ⌋ s_ls_{l+1}...s_{⌊(l+r)/2⌋} slsl+1...s(l+r)/2 is a palindrome string too.

∣ S ∣ |S| S denotes the length of string S S S.

A palindrome string is a sequence of characters which reads the same backward as forward, such as m a d a m madam madam or r a c e c a r racecar racecar or a b b a abba abba.

Input
There are multiple test cases.
Each case starts with a line containing a string S ( 1 ≤ ∣ S ∣ ≤ 3 × 1 0 5 ) S(1≤|S|≤3×10^5) S(1S3×105) containing only lowercase English letters.
It is guaranteed that the sum of ∣ S ∣ |S| S in all test cases is no larger than 4 × 1 0 6 4×10^6 4×106.

Output
For each test case, output one line containing ∣ S ∣ |S| S integers. Any two adjacent integers are separated by a space.

Sample Input

abababa

Sample Output

7 0 0 0 3 0 0

Source

2019 Multi-University Training Contest 2

题意:
给定一个字符串,问字符串中长度为 i ( 1 &lt; = i &lt; = n ) i(1&lt;=i&lt;=n) i(1<=i<=n)的符合下列条件的子串的个数
条件:
1.这个串是个回文串
2.这个串的前半部分(如果长度为奇数则要算上最中间的字符)也是回文串

题解:
枚举本质不同的回文串:回文自动机
判断一个字符串是不是回文串:哈希
枚举每种本质不同的回文串,我们可以用哈希O(1)判断他的前半部分是不是也是回文串。
然后用PAM中的每个节点的size计数即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MOD=19991227;
const int MAXN=300004;
const int D=27;
char s[MAXN];
ll bin[MAXN],Hash[2][MAXN];
int n;
void workHash(){
    Hash[0][0]=0;
    for(int i=1;i<=n;i++){
        Hash[0][i]=(Hash[0][i-1]*D+(s[i]-'a'+1))%MOD;
    }
    Hash[1][n+1]=0;
    for(int i=n;i>=1;i--){
        Hash[1][i]=(Hash[1][i+1]*D+(s[i]-'a'+1))%MOD;
    }
}
ll get(int l,int r,int x){
    if(!x){
        return (Hash[x][r]-((Hash[x][l-1]*bin[r-l+1])%MOD)+MOD)%MOD;
    }
    else{
        return (Hash[x][l]-((Hash[x][r+1]*bin[r-l+1])%MOD)+MOD)%MOD;
    }
}
bool check(int l,int r){
    return (get(l,(l+r)>>1,0)==get(l,(l+r)>>1,1));
}
struct PAM{
    int last,cnt;
    int len[MAXN],ch[MAXN][D],sz[MAXN],fa[MAXN],exi[MAXN];
    int ans[MAXN];
    int create(int Len,int Fa){
        len[cnt]=Len;
        fa[cnt]=Fa;
        return cnt++;
    }
    void CLEAR(){
        for(int i=0;i<cnt;i++){
            fa[i]=0;len[i]=0;sz[i]=0;
            memset(ch[i],0,sizeof(ch[i]));
        }
        cnt=0;
        last=0;
        create(0,1);
        create(-1,0);
    }
    int getfail(int p,int n){
        for(;s[n-len[p]-1]!=s[n];p=fa[p]);
        return p;
    }
    int add(int c,int pos){
        int p=getfail(last,pos);
        if(!ch[p][c]){
            ch[p][c]=create(len[p]+2,ch[getfail(fa[p],pos)][c]);
            exi[ch[p][c]]=check(pos-len[ch[p][c]]+1,pos);
        }
        last=ch[p][c];
        sz[last]++;
        return last;
    }
    void getans(){
        for(int i=cnt-1;i>=2;i--){
            sz[fa[i]]+=sz[i];
        }
        for(int i=cnt-1;i>=2;i--){
            ans[len[i]]+=sz[i]*exi[i];
        }
        for(int i=1;i<=n;i++){
            printf("%d",ans[i]);
            if(i==n)puts("");
            else printf(" ");
        }
    }
}pam;
int w33ha(){
    n=strlen(s+1);
    workHash();
    pam.CLEAR();
    for(int i=1;i<=n;i++)pam.ans[i]=0;
    for(int i=1;i<=n;i++)pam.add(s[i]-'a',i);
    pam.getans();
    return 0;
}
int main(){
    bin[0]=1;
    for(int i=1;i<=MAXN;i++)bin[i]=(bin[i-1]*D)%MOD;
    while(scanf("%s",s+1)!=EOF)w33ha();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值