codeforces 835D Palindromic characteristics

http://www.elijahqi.win/2018/01/07/codeforces-835d-palindromic-characteristics/
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:
3. Its left half equals to its right half.
4. 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.
dp大概真的是博大精深了吧 能想一半 但总有个槛过不去qwq 我好菜啊
设dp[i][j]表示这个区间是几阶的回文 那么如果它是n阶回文 那么它一定也是n-1 n-2 n-3…1阶回文了
那我们预处理把长度1~2的都预处理出来 然后继续dp的时候 如果我现在是l~r这个区间 如果我l+!~r-1是一个回文了 那么如果我s[l]==s[r]那么我这个l~r这个区间也一定是个回文了 而且因为回文的性质我直接答案就是我区间的一半的阶+1就是我当前回文的阶了 然后每往上更新一次我 就可以算出这个回文对比他低阶的贡献了 依次加1即可 比如一个三阶的bbbb 它可以是1阶的 也可以是2阶的 bbbb->bb bb 也可以是三阶的bbbb->bb bb->b b

#include<cstdio>
#include<cstring>
#define N 5500
char s[N];int cnt[N],dp[N][N];
int main(){
    freopen("cf.in","r",stdin);
    scanf("%s",s+1);int n=strlen(s+1);
    for (int i=1;i<=n;++i){
        dp[i][i]=1;
        ++cnt[1];if (i<n&&s[i]==s[i+1]) dp[i][i+1]=2,++cnt[2],++cnt[1];
    }
    for (int l=3;l<=n;++l){
        for (int i=1;i+l-1<=n;++i){
            if (dp[i+1][i+l-2]&&s[i]==s[i+l-1]) {
                dp[i][i+l-1]=dp[i][i+l/2-1]+1;
                for (int j=1;j<=dp[i][i+l-1];++j) ++cnt[j];
            }
        }
    }for (int i=1;i<=n;++i) printf("%d ",cnt[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值