7D - Palindrome Degree (字符串hash + DP)
原题链接
这题自己没想出来,看大佬的博客才恍然大悟,字符串哈希nb!
题意:
给定字符串,一个(k-回文串)s定义为:
s串是回文串,且s[1,n/2]是((k-1)-回文串)
(非回文串是(0-回文串))
要求计算出给定字符串所有前缀的k,并输出他们的k的和
数据范围:n<=5e6
思路:
令d[i]表示s[1,i]的k值
显然d[i]=d[n/2]+1,需要满足s[1,n/2]与s[i-n/2+1,i]互为反串
正向负向都预处理一个hash就能快速判断是否是反串了
代码如下
ull h1[N], h2[N], p[N];
int f[N];
char s[N];
ull get1(int l, int r)
{
return h1[r] - h1[l - 1] * p[r - l + 1];
}
ull get2(int l, int r)
{
return h2[l] - h2[r + 1] * p[r - l + 1];
}
int main()
{
IOS;
cin >> s + 1;
int n = strlen(s + 1);
p[0] = 1;
for(int i = 1 ; i <= n ; i ++)
{
p[i] = p[i - 1] * P;
h1[i] = h1[i - 1] * P + s[i];
}
for(int i = n ; i >= 1 ; i --)
h2[i] = h2[i + 1] * P + s[i];
f[1] = 1;
for(int i = 2 ; i <= n ; i ++)
{
int t = i / 2;
ull a = get1(1, t), b = get2(i - t + 1, i);
if(a == b)
f[i] = f[t] + 1;
}
ll res = 0;
for(int i = 1 ; i <= n ; i ++)
res += f[i];
cout << res << endl;
return 0;
}
参考:https://blog.csdn.net/weixin_44178736/article/details/107933439