题意:长度是 n 的字符串 s,如果它自身是回文数,且它的长度为 floor(n / 2)的前缀和后缀是 (k - 1)-回文数,则它被称作 k-回文数。按照定义,任何字符串 (甚至空字符串) 都是 0-回文数。
字符串 s 的回文度,被定义为这样的一个最大数 k,满足 s 是 k-回文数。例如,"abaaba" 具有的回文度是 3 。
给定一个字符串。您的任务是,找出它的全部前缀的回文度之和。
题解:dp,如果长度为i的前后缀是回文数,那么dp[i] = dp[i >> 1] + 1
那么需要解决的就是如何判断是否是回文,可以hash。
hash,只要完成一个双射即可,这就要求“基数”是质数,从左往右加和从右往左加类比数字的进位
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int maxn = 5e6 + 10;
char str[maxn];
int dp[maxn];
ULL f1[maxn], f2[maxn];
int main(){
scanf("%s", str + 1);
int l = strlen(str + 1);
ULL dig = 1;
ULL sum = 0;
dp[0] = 0;
for(int i = 1 ; i <= l; i ++){
if(str[i] >= '0' && str[i] <= '9'){
str[i] = str[i] - '0';
}else if(str[i] >= 'a' && str[i] <= 'z'){
str[i] = str[i] - 'a' + 10;
}else{
str[i] = str[i] - 'A' + 36;
}
f1[i] = f1[i - 1] * 131 + str[i];
f2[i] = (f2[i - 1] + str[i] * dig);
dig *= 131;
if(f1[i] == f2[i]){
dp[i] = dp[i >> 1] + 1;
sum += dp[i];
}
}
cout << sum << endl;
return 0;
}