• Codeforces Round #427 (Div. 2) Problem D Palindromic characteristics (Codeforces 835D)


    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:

    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 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.


      题目大意 一个k阶回文串是左右两半的串(长度为这个串的长度除以2向下取整),且这两个串都是k - 1阶回文串。统计一个串内各阶回文串的个数。

      表示这道题很简单。。然而比赛时我又把题读错。。。(我这文科渣到了某种境界)。我也不知道我怎么想的,明明看到了half,强行理解成一段。。中间那一段解释half的长度的一段,竟然成功归避。。跑去看样例猜题意了。。。绝望。。。然后不说废话了。

      根据数学的直觉和人生的哲理(瞎扯ing),可以知道,你需要用O(n^2)的时间预处理出任意一段子串是否是回文串。

      对于一个回文串是否是k阶回文串,因为它自带二分效果(因为一个回文串是对称的,所以如果它的左半边是k - 1阶回文串,那么右半边也一定是),所以可以考虑递归求解。

      据说直接求解也可以过。但是个人更喜欢把它写成记忆化搜索吧,可以省掉一个log。

      由于一个k阶回文串一定是k - 1阶回文串,所以开始就统计每个子串最高的阶数(如果不是回文串,阶数就当成0吧)的数量,最后再求个后缀和,输答案,完事。

      如果还有什么不清楚可以看代码。

    Code

     1 /**
     2  * Codeforces
     3  * Problem#835D
     4  * Accepted
     5  * Time: 171ms
     6  * Memory: 124500k
     7  */
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 int n;
    13 char s[5005];
    14 int lvls[5002][5002];
    15 boolean vis[5002][5002];
    16 int ans[5005];
    17 
    18 inline void init() {
    19     scanf("%s", s + 1);
    20     n = strlen(s + 1);
    21 }
    22 
    23 inline int getLvl(int l, int r) {
    24     if(l == r)    return 1;
    25     if(lvls[l][r] != 1 || vis[l][r])    return lvls[l][r];
    26     vis[l][r] = true;
    27     int len = (r - l + 1) / 2;
    28     return lvls[l][r] = (getLvl(l, l + len - 1) + 1);
    29 }
    30 
    31 inline void solve() {
    32     s[0] = '+', s[n + 1] = '-', s[n + 2] = 0;
    33     for(int i = 1; i <= n; i++) {
    34         lvls[i][i] = 1;
    35         int l = i - 1, r = i + 1;
    36         while(s[l] == s[r])    lvls[l][r] = 1, l--, r++;
    37         l = i, r = i + 1;
    38         while(s[l] == s[r])    lvls[l][r] = 1, l--, r++;
    39     }
    40     for(int i = 1; i <= n; i++)
    41         for(int j = i; j <= n; j++) {
    42 //            int c = getLvl(i, j);
    43 //            cout << i << " " << j << " " << c << endl;
    44             ans[getLvl(i, j)]++;
    45         }
    46     for(int i = n - 1; i; i--)
    47         ans[i] += ans[i + 1];
    48     for(int i = 1; i <= n; i++)
    49         printf("%d ", ans[i]);
    50 }
    51 
    52 int main() {
    53     init();
    54     solve();
    55     return 0;
    56 } 

      

      

  • 相关阅读:
    我的第一个MFC小项目(2)之 初涉位图
    MFC中托盘(TRAYICON)实现
    基于顺序表哈夫曼树
    对《VC中添加WM_DEVICECHANGE消息(经典)》的补充
    C++对析构函数的误解
    我的第一个MFC小项目(4)之 位图转换(续)
    (堆的应用)Huffman赫夫曼树的建立
    一个母亲一生撒的8个谎言
    线裎里面传递参数问题解决方案
    Validating user inputs using Regular Expressions
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7267342.html
Copyright © 2020-2023  润新知