https://cn.vjudge.net/problem/20907/origin
长度是 n 的字符串 s,如果它自身是回文数,且它的长度为 的前缀和后缀是 (k - 1)-回文数,则它被称作 k-回文数。按照定义,任何字符串 (甚至空字符串) 都是 0-回文数。 字符串 s 的回文度,被定义为这样的一个最大数 k,满足 s 是 k-回文数。例如,"abaaba" 具有的回文度是 3 。 给定一个字符串。您的任务是,找出它的全部前缀的回文度之和。 输入 输入数据的第一行,包含了一个非空的字符串,由拉丁字母和数字组成。字符串的长度,不超过 5·106 。字符串是大小写敏感的。 输出 输出仅有的一个数 — 字符串的全部前缀的回文度之和。
当我们想到用dp思想的时候,问题就转化为了求这个字符串每一个前缀是否是回文串的问题。
字符串hash其实和进制进位有一些相似,我们想到了这一点就可以线性的时间正着求前缀字符串的hash值和前缀字符串的倒转的hash值
当我们求正序前缀的hash的时候,每一次操作就相当于再字符串的最前面插入一个值,所以我们要首先处理出每一位的指数级ans,然后f[i] = f[i - 1] + str[i] * ans;
当我们求逆序前缀的hash值的时候,每一次操作就相当于在字符串的最后插入一个值,整个字符串就要左移一位然后把这个位塞进去 也就是f [i]= f[i - 1] * tmp + str[i];
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; const double eps = 1e-9; const int maxn = 5e6 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,tmp,K; char str[maxn]; int dp[maxn]; ULL f1[maxn],f2[maxn]; int main() { scanf("%s",str + 1); int l = strlen(str + 1); ULL ans = 1; LL 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] * ans); ans *= 131; if(f1[i] == f2[i]){ dp[i] = dp[i >> 1] + 1; sum += dp[i]; } } Prl(sum); #ifdef VSCode system("pause"); #endif return 0; }