首页 > 代码库 > SGU 232 Infinite Fraction Hash

SGU 232 Infinite Fraction Hash

题目链接:点击打开链接


#include <cstdio>
#include <cstring>
typedef unsigned long long ll;
const int key = (int)(1e9) + 7;

const int N = 150010;
char b[N], a[N + N];
ll xp[N], h[N + N];
int len;

void get() {
	char ch;
	while ((ch = getchar()) < '0' || ch > '9');
	int t = 0;
	b[t++] = ch;
	while ((ch = getchar()) >= '0' && ch <= '9')
		b[t++] = ch;
	b[t] = '\0';
}

void make(ll* h, char* s, int len) {
	h[len] = 0;
	for (int i = len - 1; i >= 0; --i)
		h[i] = h[i + 1] * key + (s[i] - '0' + 1);
}

ll H(ll *h, int st, int len) {
	return h[st] - h[st + len] * xp[len];
}
bool cmp(ll* h1, char* a1, int s1, ll* h2, char* a2, int s2) {
	if (a1[s1] != a2[s2])
		return a1[s1] > a2[s2];
	else if (H(h1, s1, len) == H(h2, s2, len))
		return true;
		
	int l = -1, r = len, mid;
	while (r - l > 1) {
		mid = (l + r) >> 1;
		if (H(h1, s1, mid) != H(h2, s2, mid))
			r = mid;
		else
			l = mid;
	}
	return a1[s1 + r - 1] > a2[s2 + r - 1];
}

int main() {
	xp[0] = 1;
	for (int i = 1; i < N; ++i)
		xp[i] = xp[i - 1] * key;

	int n, k, ansi, ansj, cc, pos;
	while(~scanf("%d%d", &n, &k)) {
		k %= n;
		//scanf("%s", b);
		get();
		if (k != 0 && n % k == 0)
			cc = k;
		else if (k == 0)
			cc = n;
		else
			cc = 1;
		len = n / cc;
		for (int i = 0; i < cc; ++i) {
			pos = i;
			for (int j = 0; j < len; ++j) {
				a[i * len * 2 + j] = a[i * len * 2 + j + len] = b[pos];
				pos = pos + k;
				if (pos >= n)
					pos -= n;
			}
			make(h + i * len * 2, a + i * len * 2, len * 2);
		}

		ansi = 0;
		ansj = 0;
		for (int i = 0; i < cc; ++i)
			for (int j = 0; j < len; ++j)
				if (cmp(h + i * len * 2, a + i * len * 2, j, h + ansi * len * 2, a + ansi * len * 2, ansj)) {
					ansi = i;
					ansj = j;
				}
				
		for (int j = 0; j < n; ++j)
			putchar(a[ansi * len * 2 + (ansj++) % len]);
		putchar('\n');
	}
	return 0;
}


SGU 232 Infinite Fraction Hash