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的字符串,问你 阶回文子串分别有多少个。 阶回文子串定义如下:
对于一个字符串,如果他本身是一个回文串,并且他的左子串和右子串都是 阶回文串,那么这个子串就是 阶回文串
【solution】
显然是dp,关键是怎么转移,
我们假设dp[i][j]表示从 到 这部分子串的阶数,容易得到
对于长度超过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;
}