D. Palindromic characteristics
time limit per test 3seconds
memory limit per test 256megabytes
Palindromic characteristics of strings with length |s| is a sequence of |s| integers, where k-th number is the total number ofnon-empty substrings of s which are k-palindromes.
A string is1-palindrome if and only if it reads the same backward asforward.
A string isk-palindrome (k > 1) if and only if:
1.Its left half equals to its right half.
2.Its left and right halfs are non-empty (k - 1)-palindromes.
The left half of stringt is its prefix of length ⌊|t| / 2⌋, and right half — thesuffix 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 appearsin the string. For example, in the string "aaa" the substring"a" appears 3 times.
Input
The first line contains the strings (1 ≤ |s| ≤ 5000) consisting oflowercase 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.
【题意】
给出一个字符串,问它分别具有多少个k级字符串。
一个回文串叫做1级回文串,一个回文串为k级回文串当且仅当它的左半部分和右半部分相同,且两部分都是(k-1)级回文串。
【思路】
显然我们发现k级字符串的得到需要(k-1)级字符串的铺垫,那么就知道可以用区间DP来解决这个问题。
我们用dp[i][j]来表示s[i]~s[j] 这一段字符串是几级回文串,如果它是一个回文串,那么在s[i-1]==s[j+1]的情况下,s[i-1]~s[j+1]就是回文串了,且其级数为前一个回文串左边一半的级数+1.
dp[i-1][j+1]=dp[i][(i+j)/2]+1.
有了这个状态转移方程基本就大功告成了。
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
const int maxn = 5005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f;
const double eps = 1e-9;
ll dp[maxn][maxn]; //s[i]~s[j]字符串的级数
bool flag[maxn][maxn]; //s[i]~s[j]是否为回文串
ll ans[maxn];
char s[maxn];
int main()
{
while(~scanf("%s",s+1))
{
mst(dp,0);
mst(flag,0);
mst(ans,0);
int n=strlen(s+1);
for(int i=1;i<=n;i++) //预处理
{
dp[i][i]=1;
flag[i][i]=1;
}
for(int len=1;len<=n;len++)
for(int i=1;i<=n;i++)
{
int j=i+len;
if(j>n) continue;
if(s[i]==s[j])
{
if(j-i==1||flag[i+1][j-1])
{
int m=(i+j)/2;
if((j-i+1)&1) m--;
flag[i][j]=1;
dp[i][j]=dp[i][m]+1;
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
ans[dp[i][j]]++;
}
for(int i=n-1;i>=1;i--)
{
ans[i]+=ans[i+1]; //级别高的回文串一定也是级别低的回文串,比如是五级回文串的话,就一定是四(3,2,1)级回文串
}
for(int i=1;i<n;i++)
{
printf("%I64d ",ans[i]);
}
printf("%I64d\n",ans[n]);
}
return 0;
}