CDOJ 1066 Palindromic String 字符串哈希/马拉车算法

时间:2023-01-03 16:57:05

就是一个一直求回文串的题,,,回文值就是递归定义的,如果它是回文串,就是它的那个子串的回文值+1,不是就是0。

然后我还自做聪明地写了一个快速幂,结果被卡了,一看当时的讲解,直接一个预处理数组就好,,,唉,,窝还是智障啊

具体不想写了,有时间再来补


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define maxn 2000005
#define p 999983
#define mod 1000000007
char str[maxn];
int idx[260];
int n;
int num[maxn];
long long hash1[maxn], hash2[maxn], powp[1000003];
long long sum = 0;
long long pow_fast(long long x, int a)
{
	long long ans = 1, tmp = x;
	for (int i = 0; i <= 20; ++i)
	{
		if ((a&(1 << i)) > 0)
		{
			ans = ans*tmp;
			if (ans >= mod)
				ans %= mod;
		}
		tmp = tmp*tmp;
		if (tmp >= mod)
			tmp %= mod;
	}
	return ans;
}
void init()
{
	for (char i = 'a'; i <= 'z'; ++i)
		idx[i] = i - 'a' + 1;
	for (int i = 'A'; i <= 'Z'; ++i)
		idx[i] = i - 'A' + 27;
	for (int i = '0'; i <= '9'; ++i)
		idx[i] = i - '0' + 53;
	powp[0] = 1;
	for (int i = 1; i < 1000003; ++i)
	{
		powp[i] = powp[i - 1] * p;
		if (powp[i] >= mod)
			powp[i] %= mod;
	}
}
int main()
{
	//freopen("input.txt", "r", stdin);
	init();
	scanf("%s", str + 1);
	n = strlen(str + 1);
	for (int i = 1; i <= n; ++i)
		hash1[i] = (hash1[i - 1] * p + idx[str[i]]) % mod;
	for (int i = n; i > 0; --i)
		hash2[i] = (hash2[i + 1] * p + idx[str[i]]) % mod;
	/*for (int i = 1; i <= n; ++i)
		printf("%lld ", hash1[i]);
	printf("\n"); 
	for (int i = n; i > 0; --i)
		printf("%lld ", hash2[i]);
	printf("\n");*/
	num[1] = 1;
	sum = 1;
	for (int i = 2; i <= n; ++i)
	{
		int mid = i / 2;
		long long l = hash1[mid];
		long long r = hash2[i - mid + 1] - hash2[i + 1] * powp[mid];
		if (r < 0 || r >= mod)
			r %= mod;
		if (r < 0)
			r += mod;
		if (l == r)
			num[i] = num[mid] + 1;
		sum += (long long)num[i];
	}
	/*for (int i = 1; i <= n; ++i)
		printf("%d ", num[i]);
	printf("\n");*/
	printf("%lld", sum);
	//system("pause");
	//while (1);
	return 0;
}