[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