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

posted @ 2021-04-05 21:22  beatlesss  阅读(76)  评论(0编辑  收藏  举报