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
    
    
  • 相关阅读:
    Maximum Flow Exhaustion of Paths Algorithm
    ubuntu下安装java环境
    visualbox使用(二)
    vxworks一个超级奇怪的错误(parse error before `char')
    February 4th, 2018 Week 6th Sunday
    February 3rd, 2018 Week 5th Saturday
    February 2nd, 2018 Week 5th Friday
    February 1st, 2018 Week 5th Thursday
    January 31st, 2018 Week 05th Wednesday
    January 30th, 2018 Week 05th Tuesday
  • 原文地址:https://www.cnblogs.com/mollnn/p/14366782.html
Copyright © 2011-2022 走看看