很容易想到对于原串的两端,选择字典序最小的,如果相同,则往里面找,找到不相同的再比较大小,取最小的。可以用字符串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 <typename T>
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(); //ÏàµÈµÄ³¤¶È
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('
');
}
return 0;
}