P6140 [USACO07NOV]Best Cow Line S


很容易想到对于原串的两端,选择字典序最小的,如果相同,则往里面找,找到不相同的再比较大小,取最小的。可以用字符串hash优化到\(O(n log n)\)


const int N = 5e5 + 79;
int n, len;
char s[N];
char ans[N];
const ull base = 1e9 + 7;
ull h[N], hash1[N],hash2[N];

int L, R;

inline ull H1(int l, int r) {
	return hash1[r] - hash1[l - 1] * h[r - l + 1];
}

inline ull H2(int r, int l) {
	return hash2[r] - hash2[l + 1] * h[l - r + 1];
}

inline bool check(int len) {
	return H1(L, L + len - 1) == H2(R - len + 1, R);
}



inline char gt() {
	static char buf[1 << 21], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
template 
inline void  read(T &x) {
	char ch = gt();
	x = 0;
	int w(0);
	while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
	while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
	w ? x = ~(x - 1) : x;
}

inline int find() {
	int l(1), r( (R - L + 1) >> 1 ), mid, ans(1);
	while(l <= r) {
		mid = (l + r) >> 1;
		if(check(mid)) {
			l = mid + 1;
			ans = mid;
		} else {
			r = mid - 1;
		}
	}
	return ans;
}



int main() {
read(n);
	s[0] = '0';
	rep(i, 1, n) {
		while((s[i]=gt())<'A'||s[i]>'Z');
	}
	h[0] = 1;
	rep(i, 1, n) {
		h[i] = h[i - 1] * base;
		hash1[i] = hash1[i - 1] * base + s[i];
	}
	drp(i, n, 1) {
		hash2[i] = hash2[i + 1] * base + s[i];
	}

	L = 1, R = n;
	ans[0] = '0';
	while(L < R) {
		if(s[L] < s[R]) {
			ans[++len] = s[L++];
		} else if(s[L] > s[R]) {
			ans[++len] = s[R--];
		} else {
			int Len = find(); //?àμèμ?3¤?è
			ans[++len] = s[L + Len] < s[R - Len] ? s[L++] : s[R--];
		}
	}
	ans[++len] = s[L];
	rep(i, 1, len) {
		putchar(ans[i]);
		if(!(i % 80)) putchar('\n');
	}
	return 0;
}