POI2012PRE-Prefixuffix

xiaruize發表於2024-04-25

POI #Year2012 #kmp

考慮相當於把原串分成 \(abcba\) 的串,使得 \(ab\) 儘可能長

然後從後往前列舉後面的 \(a\) 長度,然後對於 \(b\) 的長度考慮 \(dp_i=dp_{i+1}+2\),然後往下縮小直到合法

// Author: xiaruize
const int N = 1e6 + 10;

int n;
char s[N];
int nxt[N];
int hsh[N], pw[N];
int dp[N];

ull get(int l, int r)
{
	return ((hsh[r] - hsh[l - 1] * pw[r - l + 1] % MOD) % MOD + MOD) % MOD;
}

void solve()
{
	cin >> n >> (s + 1);
	pw[0] = 1;
	rep(i, 1, n)
	{
		hsh[i] = (hsh[i - 1] * 13331 % MOD + s[i]) % MOD;
		pw[i] = pw[i - 1] * 13331 % MOD;
	}
	for (int i = 2, j = 0; i <= n; i++)
	{
		while (j && s[j + 1] != s[i])
			j = nxt[j];
		if (s[j + 1] == s[i])
			j++;
		nxt[i] = j;
	}
	per(i, n / 2, 1)
	{
		dp[i] = dp[i + 1] + 2;
		while (dp[i] && ((dp[i] + i) * 2 > n || get(i + 1, i + dp[i]) != get(n - i - dp[i] + 1, n - i)))
			dp[i]--;
	}
	int x = nxt[n];
	int res = 0;
	while (x)
	{
		if (x * 2 <= n)
		{
			res = max(res, x + dp[x]);
		}
		x = nxt[x];
	}
	cout << res << endl;
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	// cin >> testcase;
	while (testcase--)
		solve();
#ifndef ONLINE_JUDGE
	cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
	cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
	return 0;
}