【BZOJ2795】[Poi2012]A Horrible Poem【Hash】【GCD】【暴力】

【題目鏈接】

【POPOQQQ的題解】

跑了倒數rk5...

/* Think Thank Thunk */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;

const int maxn = 500005;

int n, m, sum[26][maxn];
char str[maxn];
ULL hash[2][maxn], power[2][maxn], seed[] = {233, 997}, mod[] = {1000000009, 1000000007};

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

inline int gcd(int a, int b) {
	for(; b; b ^= a ^= b ^= a %= b);
	return a;
}

inline bool check(int l, int r, int len) {
	len = r - l + 1 - len;
	for(int j = 0; j < 2; j++) {
		ULL a = (hash[j][l + len - 1] + mod[j] - (hash[j][l - 1] * power[j][len]) % mod[j]) % mod[j];
		ULL b = (hash[j][r] + mod[j] - (hash[j][r - len] * power[j][len]) % mod[j]) % mod[j];
		if(a != b) return 0;
	}
	return 1;
}

inline int query(int l, int r) {
	int len = r - l + 1;
	int k = len;
	for(int i = 0; i < 26; i++) k = gcd(k, sum[i][r] - sum[i][l - 1]);

	int res = len;
	for(int i = 1; i * i <= k; i++) if(k % i == 0) {
		if(check(l, r, len / i)) res = min(res, len / i);
		if(check(l, r, len / (k / i))) res = min(res, len / (k / i));
	}
	return res;
}

int main() {
	n = iread();
	scanf("%s", str + 1);

	for(int j = 0; j < 26; j++) for(int i = 1; i <= n; i++)
		sum[j][i] = sum[j][i - 1] + (str[i] == (j + 'a'));
	power[0][0] = power[1][0] = 1;
	for(int j = 0; j < 2; j++) for(int i = 1; i <= n; i++) {
		hash[j][i] = (hash[j][i - 1] * seed[j] + (str[i] - 'a')) % mod[j];
		power[j][i] = (power[j][i - 1] * seed[j]) % mod[j];
	}

	m = iread();
	while(m--) {
		int l = iread(), r = iread();
		printf("%d\n", query(l, r));
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章