P3546 [POI2012] PRE-Prefixuffix
Upd on 2022.9.4:修改表述。
*P3546 [POI2012] PRE-Prefixuffix
POI 合集。
好题。
若
考虑所有
根据这一性质,我们从大到小枚举所有
判断字符串是否相等使用哈希,自然溢出哈希会被卡。求
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define TIME 1e3 * clock() / CLOCKS_PER_SEC
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
inline int read() {
int x = 0;
char s = getchar();
while(!isdigit(s)) s = getchar();
while(isdigit(s)) x = x * 10 + s - '0', s = getchar();
return x;
}
inline void print(int x) {
if(x < 0) return putchar('-'), print(-x);
if(x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
bool Mbe;
constexpr int N = 1e6 + 5;
constexpr int mod = 1e9 + 7;
int n, ans, f[N], nxt[N], hsh[N], pw[N];
int calc(int l, int r) {return l--, (hsh[r] - 1ll * hsh[l] * pw[r - l] % mod + mod) % mod;}
char s[N];
bool Med;
int main() {
fprintf(stderr, "%.3lf MB\n", (&Mbe - &Med) / 1048576.0);
#ifdef ALEX_WEI
FILE* IN = freopen("1.in", "r", stdin);
FILE* OUT = freopen("1.out", "w", stdout);
#endif
ios::sync_with_stdio(0);
cin >> n >> s + 1;
for(int i = pw[0] = 1; i <= n; i++) pw[i] = 1ll * pw[i - 1] * 131 % mod;
for(int i = 2, j = 0; i <= n; i++) {
while(j && s[j + 1] != s[i]) j = nxt[j];
nxt[i] = j += s[j + 1] == s[i];
}
for(int i = 1; i <= n; i++) hsh[i] = (1ll * hsh[i - 1] * 131 + s[i]) % mod;
for(int i = n / 2; i; i--) {
f[i] = f[i + 1] + 2;
while(f[i]) {
if((i + f[i]) * 2 > n) f[i]--;
else if(calc(i + 1, i + f[i]) != calc(n - i - f[i] + 1, n - i)) f[i]--;
else break;
}
}
for(int i = nxt[n]; i; i = nxt[i]) if(i * 2 <= n) ans = max(ans, f[i] + i);
cout << ans << "\n";
cerr << TIME << " ms\n";
return 0;
}
/*
2022/9/4
author: Alex_Wei
start coding at 8:40
finish debugging at 8:50
*/