[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

原文地址:https://www.cnblogs.com/mollnn/p/14366782.html