zoukankan      html  css  js  c++  java
  • [CF7D] Palindrome Degree

    [CF7D] Palindrome Degree - dp

    Description

    一个长度为 n 字符串 s 被叫做 k 阶级回文串,当且仅当它本身是一个回文串,而且它长度为 n/2 的前缀和后缀都是 k-1 阶级回文串。任何一个字符串(包括空字符串)都至少是 0 阶级字符串。现在给定你一字符串,请你求出其所有前缀的的阶级之和。

    Solution

    (f[i]) 表示长度为 i 的前缀的阶数,如果是回文的,那么 (f[i]=f[i/2]+1),否则 (f[i]=0)

    判断回文可以直接 Manacher

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    // Input: str[] (0-index)
    // Method: solve()
    // Output: a[] (i -> i*2+1)
    namespace man
    {
        const int N = 11000005;
        char str[N], s[N << 1];
        int a[N << 1];
    
        int manacher(int len)
        {
            a[0] = 0;
            int ans = 0, j;
            for (int i = 0; i < len;)
            {
                while (i - a[i] > 0 && s[i + a[i] + 1] == s[i - a[i] - 1])
                    a[i]++;
                if (ans < a[i])
                    ans = a[i];
                j = i + 1;
                while (j <= i + a[i] && i - a[i] != i + i - j - a[i + i - j])
                {
                    a[j] = min(a[i + i - j], i + a[i] - j);
                    j++;
                }
                a[j] = max(i + a[i] - j, 0ll);
                i = j;
            }
            /* 以下代码用于生成每个点(原始,1-index)开始的最长回文长度
        for(int i=0;i<len;i++) l[i]=0;
        for(int i=0;i<len;i++) l[i-a[i]+1]=max(l[i-a[i]+1],a[i]);
        for(int i=0;i<len;i++) l[i]=max(l[i],l[i-2]-2);
        for(int i=1;i<=len;i++) l[i]=l[i*2-1];
        */
            return ans;
        }
    
        int solve()
        {
            int len;
            len = 2 * strlen(str) + 1;
            for (int i = 0; str[i] != ''; i++)
            {
                s[i + i] = '';
                s[i + i + 1] = str[i];
            }
            s[len - 1] = '';
            return manacher(len);
        }
    } // namespace man
    
    // For Test
    signed main()
    {
        scanf("%s", man::str);
        man::solve();
    
        auto &str = man::str;
        int n = strlen(str);
        vector<int> f(n + 2);
        int ans = 0;
        for (int i = 1; i <= n; i++)
            if (man::a[i] >= i)
                f[i] = f[i / 2] + 1, ans += f[i];
        cout << ans << endl;
    }
    // Input: abcbcbcabc
    // Output: 5
    
    
  • 相关阅读:
    Java 面向对象_继承
    Java 面向对象
    使用 pykafka 进行消费
    oracle 的分页、截断查询
    Day03
    Day02 计算机的组成与编程语言
    Day01 MarkDown的使用
    Java方法的重点
    Scanner的小细节
    Java包机制和Javadoc的使用
  • 原文地址:https://www.cnblogs.com/mollnn/p/14366782.html
Copyright © 2011-2022 走看看