codeforces round#427D Palindromic characteristics

Open the transmission gate

Palindromic characteristics of string s with length |s| is a sequence of |s| integers, where k-th number is the total number of non-empty substrings of s which are k-palindromes.

A string is 1-palindrome if and only if it reads the same backward as forward.

A string is k-palindrome (k > 1) if and only if:

    Its left half equals to its right half.
    Its left and right halfs are non-empty (k - 1)-palindromes. 

The left half of string t is its prefix of length ⌊|t| / 2⌋, and right half — the suffix of the same length. ⌊|t| / 2⌋ denotes the length of string t divided by 2, rounded down.

Note that each substring is counted as many times as it appears in the string. For example, in the string "aaa" the substring "a" appears 3 times.

Input

The first line contains the string s (1 ≤ |s| ≤ 5000) consisting of lowercase English letters.

Output

Print |s| integers — palindromic characteristics of string s.

Examples
Input

abba

Output

6 1 0 0 

Input

abacaba

Output

12 4 1 0 0 0 0 

Note

In the first example 1-palindromes are substring «a», «b», «b», «a», «bb», «abba», the substring «bb» is 2-palindrome. There are no 3- and 4-palindromes here.

translation

给你一个长度不超过5000的字符串,问你 K 阶回文子串分别有多少个。 K 阶回文子串定义如下:

对于一个字符串,如果他本身是一个回文串,并且他的左子串和右子串都是 K 1 阶回文串,那么这个子串就是 K 阶回文串

solution

显然是dp,关键是怎么转移,

我们假设dp[i][j]表示从 i j 这部分子串的阶数,容易得到
d p [ i ] [ i ] = 1
d p [ i ] [ i + 1 ] = ( q u e [ i ] == q u e [ i + 1 ] ? 2 : 0 )
对于长度超过2的子串我们直接用前面的答案递推就行了。
稍微要注意的一点就是如果一个子串是K阶子串那么显然他也是一个(k-1)阶子串,所以我们统计答案的时候记得累加一下。

code

#include <bits/stdc++.h>
using namespace std;
const int maxm = 5e3+10;
char que[maxm];
int dp[maxm][maxm];
int ans[maxm];
int main() {
    //freopen("C:\\Users\\ACM2018\\Desktop\\in.txt","r",stdin);
    scanf("%s",que);
    int len = strlen(que);
    for(int i = 0;i<len;i++){///枚举长度
        for(int l = 0;l+i<len;l++){///枚举一个左节点
            if(i==0) dp[l][l+i] = 1;///长度为1的是一阶回文
            else if(i==1)///长度为2的可能是不回文或者二阶回文
                dp[l][i+l] = (que[l]==que[l+1]?2:0);
            else if(que[l]==que[i+l]&&dp[l+1][l+i-1]){///首先保证这个子串回文
                dp[l][l+i] = 1;
                int mid = (l+l+i)>>1;
                if(i&1){
                    if(dp[l][mid]&&dp[mid+1][l+i]){
                        dp[l][l+i] = dp[l][mid]+1;
                    }
                }
                else {
                    if(dp[l][mid-1]&&dp[mid+1][l+i]){
                        dp[l][l+i] = dp[l][mid-1]+1;
                    }
                }
            }
        }
    }
    for(int i = 0;i<len;i++){
        for(int j = i;j<len;j++){
            ans[dp[i][j]]++;
        }
    }
    for(int i = len-1;i>=0;i--){
        ans[i]+=ans[i+1];
    }
    for(int i = 1;i<=len;i++){
        printf("%d ",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mengzhongsharen/article/details/80168713