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
    
    
  • 相关阅读:
    Life Forms POJ
    Maximum repetition substring POJ
    Extend to Palindrome UVA
    Sequence POJ
    HDU-6705 path (bfs)
    632C. The Smallest String Concatenation(注意 :stl sort函数坑点--- coredump问题 )
    2018 ICPC青岛网络赛 B. Red Black Tree(倍增lca)
    基于哈希表实现页面置换算法
    解决xpath中文乱码
    解决oh-my-zsh中git分支显示乱码问题
  • 原文地址:https://www.cnblogs.com/mollnn/p/14366782.html
Copyright © 2011-2022 走看看